Python 基于来自另一个数组的数据对numpy数组进行排序
我有两组数组Python 基于来自另一个数组的数据对numpy数组进行排序,python,sorting,numpy,Python,Sorting,Numpy,我有两组数组数据和结果结果在数据中包含相同的元素,但有一个额外的列,且未排序。我想重新排列结果数组,使其与数据中的行的顺序相同,同时在排序时将关联的值与行的其余部分一起放入最后一列 data = np.array([[0,1,0,0],[1,0,0,0],[0,1,1,0],[0,1,0,1]]) result = np.array([[0,1,1,0,1],[1,0,0,0,0],[0,1,0,0,1],[0,1,0,1,0]]) # this is what the final sorte
数据
和结果
<代码>结果在数据
中包含相同的元素,但有一个额外的列,且未排序。我想重新排列结果
数组,使其与数据
中的行的顺序相同,同时在排序时将关联的值与行的其余部分一起放入最后一列
data = np.array([[0,1,0,0],[1,0,0,0],[0,1,1,0],[0,1,0,1]])
result = np.array([[0,1,1,0,1],[1,0,0,0,0],[0,1,0,0,1],[0,1,0,1,0]])
# this is what the final sorted array should look like:
'''
array([[0, 1, 0, 0, 1],
[1, 0, 0, 0, 0],
[0, 1, 1, 0, 1],
[0, 1, 0, 1, 0]])
'''
我尝试过使用argsort
将数据
反转为排序顺序,然后将其应用于结果
,但是argsort
似乎根据每个元素对数组的顺序进行排序,而我希望排序将数据[:,4]
的每一行作为一个整体处理
ind = np.argsort(data)
indind =np.argsort(ind)
ind
array([[0, 2, 3, 1],
[1, 2, 3, 0],
[0, 3, 1, 2],
[0, 2, 1, 3]])
按行进行这种排序的好方法是什么 只是想弄清楚你在做什么。使用索引列表
[2,1,0,3]
我可以对结果的行重新排序,因此:
In [37]: result[[2,1,0,3],:]
Out[37]:
array([[0, 1, 0, 0, 1],
[1, 0, 0, 0, 0],
[0, 1, 1, 0, 1],
[0, 1, 0, 1, 0]])
In [38]: result[[2,1,0,3],:4]==data
Out[38]:
array([[ True, True, True, True],
[ True, True, True, True],
[ True, True, True, True],
[ True, True, True, True]], dtype=bool)
我看不出argsort
或sort
将如何帮助制定这个索引顺序
使用np.lexsort
我可以对两个数组的行进行相同的排序:
In [54]: data[np.lexsort(data.T),:]
Out[54]:
array([[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 1, 1, 0],
[0, 1, 0, 1]])
In [55]: result[np.lexsort(result[:,:-1].T),:]
Out[55]:
array([[1, 0, 0, 0, 0],
[0, 1, 0, 0, 1],
[0, 1, 1, 0, 1],
[0, 1, 0, 1, 0]])
通过反复试验,我发现我需要使用转置。我们需要检查lexsort
的文档以了解原因
再多一点尝试和错误就会产生:
In [66]: i=np.lexsort(data.T)
In [67]: j=np.lexsort(result[:,:-1].T)
In [68]: j[i]
Out[68]: array([2, 1, 0, 3], dtype=int64)
In [69]: result[j[i],:]
Out[69]:
array([[0, 1, 0, 0, 1],
[1, 0, 0, 0, 0],
[0, 1, 1, 0, 1],
[0, 1, 0, 1, 0]])
这是一个初步的解决办法。它需要在其他样品上进行测试。需要解释。方法#1
这是一种将每一行视为索引元组的方法,然后找到与这些线性索引等价物对应的数据
和结果
之间的匹配索引。这些索引将表示新的行顺序,当索引到结果中时,将为我们提供所需的输出。实现如下所示-
# Slice out from result everything except the last column
r = result[:,:-1]
# Get linear indices equivalent of each row from r and data
ID1 = np.ravel_multi_index(r.T,r.max(0)+1)
ID2 = np.ravel_multi_index(data.T,r.max(0)+1)
# Search for ID2 in ID1 and use those indices index into result
out = result[np.where(ID1[:,None] == ID2)[1]]
方法#2
如果数据
中的所有行都保证在结果
中,则可以使用另一种基于argsort
的方法,如下所示-
# Slice out from result everything except the last column
r = result[:,:-1]
# Get linear indices equivalent of each row from r and data
ID1 = np.ravel_multi_index(r.T,r.max(0)+1)
ID2 = np.ravel_multi_index(data.T,r.max(0)+1)
sortidx_ID1 = ID1.argsort()
sortidx_ID2 = ID2.argsort()
out = result[sortidx_ID1[sortidx_ID2]]
运行示例以了解更一般的情况-
In [37]: data
Out[37]:
array([[ 3, 2, 1, 5],
[ 4, 9, 2, 4],
[ 7, 3, 9, 11],
[ 5, 9, 4, 4]])
In [38]: result
Out[38]:
array([[ 7, 3, 9, 11, 55],
[ 4, 9, 2, 4, 8],
[ 3, 2, 1, 5, 7],
[ 5, 9, 4, 4, 88]])
In [39]: r = result[:,:-1]
...: ID1 = np.ravel_multi_index(r.T,r.max(0)+1)
...: ID2 = np.ravel_multi_index(data.T,r.max(0)+1)
...:
In [40]: result[np.where(ID1[:,None] == ID2)[1]] # Approach 1
Out[40]:
array([[ 3, 2, 1, 5, 7],
[ 4, 9, 2, 4, 8],
[ 7, 3, 9, 11, 55],
[ 5, 9, 4, 4, 88]])
In [41]: sortidx_ID1 = ID1.argsort() # Approach 2
...: sortidx_ID2 = ID2.argsort()
...:
In [42]: result[sortidx_ID1[sortidx_ID2]]
Out[42]:
array([[ 3, 2, 1, 5, 7],
[ 4, 9, 2, 4, 8],
[ 7, 3, 9, 11, 55],
[ 5, 9, 4, 4, 88]])
该软件包(免责声明:我是其作者)可用于高效、优雅地解决此类问题:
import numpy_indexed as npi
result[npi.indices(result[:, :-1], data)]
npi.index本质上是list.index的向量化等价物;所以对于数据中的每个元素(行),我们得到了结果中相同行的位置,减去最后一列
请注意,此解决方案适用于任意数量的列,并且是完全矢量化的(即,任何地方都没有python循环)。额外的列是否总是放在序列的最后?此答案适用于我上面给出的示例这样的小数据集,但当我使用更大的示例(5172x32数据集)时,它会给出错误“ValueError:传递给ravel_multi_index的维度太多了”。我该如何解决这个问题?@ROBOTPWNS计算那些ID1和ID2,像这样,看看它是否有效:ID1=r.dot(r.max(0)+1);ID2=data.dot(r.max(0)+1)
?不,这不起作用,我只是在序列混淆之前重建了数组,然后根据这些标记取消了排序。不过谢谢。