Python argsort索引上的numpy累积和排序

Python argsort索引上的numpy累积和排序,python,arrays,numpy,Python,Arrays,Numpy,背景 我试图计算一组点之间的“社交旅行者”距离。对于两个点a和b,我们将ST(a,b)定义为a和所有比b更接近a的点之间欧几里德距离的累积和,直到并包括b (假设a正在进行各种旅行以探望人们。他们首先看到最近的人,然后是下一个最近的人,依此类推。社交旅行距离是他们到达b时将旅行的距离(仅计算出发距离) 社会出行距离定义为任意半径;除此之外,“已访问”点被定义为无法访问。这是因为(原因) 我到目前为止所做的事情 我有一个带点的numpy数组。玩具示例: >>> import nu

背景

我试图计算一组点之间的“社交旅行者”距离。对于两个点a和b,我们将ST(a,b)定义为a和所有比b更接近a的点之间欧几里德距离的累积和,直到并包括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)
因为这是基于行顺序而不是排序进行添加,所以它给出了错误的值(这里第一行的巧合除外)。我也可以这样做,首先对行进行排序:

>>> 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值进行定位:

似乎我需要一种方法对这些行进行排序,进行累积和,然后返回按这些argsort向量排序的累积和。请注意,如果您按
np.argsort(ym)
中的向量对
np.cumsum(np.sort(ym,axis=1),axis=1)的结果进行排序,那么您就得到了my
假设新数组。但这是最后一步,我要摔倒在地

我觉得这里有三分之二的维恩图。你有没有想过我该如何迈出最后一步?我希望这是我所发现的numpy语法知识中的一个相对简单的缺口

编辑:在张贴并继续挖掘之后,我想我找到了“明显的”答案,用<代码> NP.TuangYangLangxAxIS()/<代码>——但不。考虑这个代码:

>>> 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
的第四个元素并将其放置在第一个位置,最后一行
bar
的第三个元素并将其放置在第二个位置,以此类推(回想一下,foo的最后一行是
[4,3,0,1,2]
)我想取而代之的是把最后一行的1st元素放在4th点,把
bar
2nd元素放在3th点,等等,然后
np。沿轴放置不是我的障碍,或者。

为不理解这些要求而道歉。我又试了一次,想出了这个。我不知道如何使用for循环来实现这一点,但输出似乎与您假设的新值相匹配,第一行中的舍入问题除外。但我认为逻辑应该成立

>>> 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)

有点笨重,如果我又错了,我会举白旗道歉,因为我没有尽快做出反应——如果我只是说“全球大流行”,希望这能解释为什么?这确实产生了想要的阵列!现在的问题是,是否有一种方法可以消除其中的for循环,只是为了提高效率。但这将问题带到了一个新的阶段,对此我非常感激。@JPFerguson,是的,这些天整个世界都在以不同的速度前进