【发布时间】:2020-07-26 17:00:34
【问题描述】:
背景
我正在尝试计算一组点之间的“社交旅行者”距离。对于两点a和b,我们定义ST(a,b)为a之间的欧式距离之和em> 以及比 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)
这给了我正确的值,但它们是按升序排列的,而不是我想要的顺序。我希望这些累积和根据原始数组的 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.argsort(ym) 中的向量排序的np.cumsum(np.sort(ym, axis=1), axis=1) 的结果,您就有了我的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 个元素放在第一个位置,即@ 最后一行的第3 个元素987654333@ 并将其放在第二个位置,依此类推(回想一下 foo 的最后一行是 [4, 3, 0, 1, 2]。)我想要的是取 @987654335 最后一行的 1st 元素@ 放在第四点,bar的2nd元素放在第三点,以此类推@987654337 @ 也不是我的果酱。
【问题讨论】: