python - 在 argsort 索引上排序的 numpy 累积和

标签 python arrays numpy

背景

我正在尝试计算一组点之间的“社交旅行者”距离。对于 ab 两个点,我们将 ST(a,b) 定义为 ab 更接近 的所有点,直至并包括 b

(假设 a 正在进行各种旅行以拜访人们。他们首先会见最近的人,然后是下一个最近的人,依此类推。社会旅行者距离是他们旅行的距离(只计算离开的距离)到他们到达 b 时。)

社会旅行者距离被定义为某个任意半径;除此之外,“访问过”的点被定义为无法到达。这是因为原因。 ;)

到目前为止我做了什么

我有一个带有点的 numpy 数组。玩具示例:

>>> import numpy as np
>>> x = np.array([(0,0), (-1,2), (-2,-2), (6,-2), (4,0)])
>>> x
array([[ 0,  0],
       [-1,  2],
       [-2, -2],
       [ 6, -2],
       [ 4,  0]])

我生成一个数组,其中包含每个点之间的成对距离。对于这个例子,距离 4 是我考虑的上限。

>>> from sklearn.metrics import pairwise_distances
>>> y = pairwise_distances(x)
>>> y
array([[0.  , 2.24, 2.83, 6.32, 4.  ],
       [2.24, 0.  , 4.12, 8.06, 5.39],
       [2.83, 4.12, 0.  , 8.  , 6.32],
       [6.32, 8.06, 8.  , 0.  , 2.83],
       [4.  , 5.39, 6.32, 2.83, 0.  ]])
>>> import numpy.ma as ma
>>> ym = ma.masked_greater(y, 4)
>>> ym
masked_array(
  data=[[0.0 , 2.24, 2.83,   --, 4.0 ],
        [2.24, 0.0 ,   --,   --,   --],
        [2.83,   --, 0.0 ,   --,   --],
        [  --,   --,   --, 0.0 , 2.83],
        [4.0 ,   --,   --, 2.83, 0.0 ]],
  mask=[[False, False, False,  True, False],
        [False, False,  True,  True,  True],
        [False,  True, False,  True,  True],
        [ True,  True,  True, False, False],
        [False,  True,  True, False, False]],
  fill_value=1e+20)

(为了大家的理智,我截断了数字。)

我的目标是用该行非缺失值的累计和替换每个行元素,直至并包括该元素。 (为简单起见,忽略关系问题。)即我想得到这个数组:

>>> hypothetical_new_y
array([[0.  , 2.24, 5.06,  nan, 9.06],
       [2.24, 0.  ,  nan,  nan,  nan],
       [2.83,  nan, 0.  ,  nan,  nan],
       [nan ,  nan,  nan, 0.  , 2.83],
       [6.83,  nan,  nan, 2.83, 0.  ]])

我知道如何获取行的累计和:

>>> np.cumsum(ym, axis=1)
masked_array(
  data=[[0.0 , 2.24, 5.06,   --, 9.06],
        [2.24, 2.24,   --,   --,   --],
        [2.83,   --, 2.83,   --,   --],
        [  --,   --,   --, 0.0 , 2.83],
        [4.0 ,   --,   --, 6.83, 6.83]],
...

因为这是根据行顺序添加而不是排序,所以它给出了不正确的值(除了这里第一行的巧合)。我可以这样做,首先对行进行排序:

>>> np.cumsum(np.sort(ym, axis=1), axis=1)
masked_array(
  data=[[0.0 , 2.24, 5.06, 9.06,   --],
        [0.0 , 2.24,   --,   --,   --],
        [0.0 , 2.83,   --,   --,   --],
        [0.0 , 2.83,   --,   --,   --],
        [0.0 , 2.83, 6.83,   --,   --]],
  mask=[[False, False, False, False,  True],
        [False, False,  True,  True,  True],
        [False, False,  True,  True,  True],
        [False, False,  True,  True,  True],
        [False, False, False,  True,  True]],
  fill_value=1e+20)

这给了我正确的值,但它们是按升序而不是我想要的顺序排序的。我希望这些累计和根据原始数组的 argsort 值定位:

>>> np.argsort(ym)
array([[0, 1, 2, 4, 3],
       [1, 0, 2, 3, 4],
       [2, 0, 1, 3, 4],
       [3, 4, 0, 1, 2],
       [4, 3, 0, 1, 2]])

看来我需要一种方法来对这些行进行排序,计算累加和,然后返回按那些 argsort 向量排序的累加和。请注意,如果您显示 np.cumsum(np.sort(ym, axis=1), axis=1) 的结果按 np.argsort(ym) 中的向量排序,你有我的hypothethical_new_y大批。但这是我摔倒在地的最后一步。

我觉得我这里有维恩图的三分之二。关于如何迈出这最后一步有什么想法吗?我希望这是我发现的 numpy 语法知识中一个相对简单的差距。

编辑:发布此内容并继续挖掘后,我认为我已经通过 np.take_along_axis() 找到了“显而易见”的答案。 - 但不是。考虑这段代码:

>>> foo = np.argsort(ym)
>>> bar = np.cumsum(np.sort(ym, axis=1), axis=1)
>>> np.take_along_axis(bar, foo, axis=1)
masked_array(
  data=[[0.0 , 2.24, 5.06,   --, 9.06],
        [2.24, 0.0 ,   --,   --,   --],
        [  --, 0.0 , 2.83,   --,   --],
        [  --,   --, 0.0 , 2.83,   --],
        [  --,   --, 0.0 , 2.83, 6.83]],
...

例如,如果您查看最后一行,很明显该命令正在获取 bar 最后一行的第 4 个元素。并将其放在第一个位置,即 bar 最后一行的第三个元素并将它放在第二个位置等。(回想一下 foo 的最后一行是 [4, 3, 0, 1, 2] 。)我想要的是取 bar 最后一行的 1st 元素。并将其放在第四 位置,即bar2 元素|并将其放在第三 位置等。并且np.put_along_axis也不是我的果酱。

最佳答案

抱歉未能理解要求。我又试了一次,想出了这个。我无法弄清楚如何使用 for 循环执行此操作,但输出似乎与您的 hypothetical_new_y 匹配,除了第一行中的舍入问题。但我认为这个逻辑应该成立。

>>> x
array([[ 0.  ,  2.24,  2.83,  6.32,  4.  ],
       [ 2.24,  0.  ,  4.12,  8.06,  5.39],
       [ 2.83,  4.12,  0.  ,  8.  ,  6.32],
       [ 6.32,  8.06,  8.  ,  0.  ,  2.83],
       [ 4.  ,  5.39,  6.32,  2.83,  0.  ]])
>>> ym
masked_array(data =
 [[0.0 2.24 2.83 -- 4.0]
 [2.24 0.0 -- -- --]
 [2.83 -- 0.0 -- --]
 [-- -- -- 0.0 2.83]
 [4.0 -- -- 2.83 0.0]],
             mask =
 [[False False False  True False]
 [False False  True  True  True]
 [False  True False  True  True]
 [ True  True  True False False]
 [False  True  True False False]],
       fill_value = 1e+20)

>>> g=np.cumsum(np.sort(ym, axis=1), axis=1)
>>> g
masked_array(data =
 [[0.0 2.24 5.07 9.07 --]
 [0.0 2.24 -- -- --]
 [0.0 2.83 -- -- --]
 [0.0 2.83 -- -- --]
 [0.0 2.83 6.83 -- --]],
             mask =
 [[False False False False  True]
 [False False  True  True  True]
 [False False  True  True  True]
 [False False  True  True  True]
 [False False False  True  True]],
       fill_value = 1e+20)
>>> n = np.zeros_like(x, dtype=float).view(np.ma.masked_array)
>>> for i in range(n.shape[0]):
...         n[i][x[i].argsort(axis=0)] = g.data[i]
...         
>>> 
>>> n.mask = ym.mask
>>> n
masked_array(data =
 [[0.0 2.24 5.07 -- 9.07]
 [2.24 0.0 -- -- --]
 [2.83 -- 0.0 -- --]
 [-- -- -- 0.0 2.83]
 [6.83 -- -- 2.83 0.0]],
             mask =
 [[False False False  True False]
 [False False  True  True  True]
 [False  True False  True  True]
 [ True  True  True False False]
 [False  True  True False False]],
       fill_value = 1e+20)

有点笨拙,如果我再错了,我会举起白旗 😕

关于python - 在 argsort 索引上排序的 numpy 累积和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63103165/

相关文章:

python - 在 *args 中传递一个元组

python - Locust 中的动态 GET 参数

javascript - 如何在 NodeRED 数组中收集从 angularJS 发送的字符串?

python - 想要比 numpy.take 更快的索引吗?

Javascript:从对象中查找值

python - 通过回溯迭代图像

python - 排除优先级较低的重复元素 (Django)

python - numpy 用 2*2 block 的平均值替换数组元素

Python绘图对数刻度设置xticks?

python - 如何运行 ajax 请求处理程序 Tornado