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