Python如何查找唯一条目并从匹配的数组中获取最小值

时间:2015-10-18 01:32:50

标签: python arrays numpy

我有一个numpy数组,indices

array([[ 0,  0,  0],
       [ 0,  0,  0],
       [ 2,  0,  2],
       [ 0,  0,  0],
       [ 2,  0,  2],
       [95, 71, 95]])

我有另一个长度相同的数组distances

array([  0.98713981,   1.04705992,   1.42340327, 74.0139111 ,
    74.4285216 ,  74.84623217])

indices中的所有行都在distances数组中匹配。问题是,indices数组中存在重复项,并且它们在相应的distances数组中具有不同的值。我希望获得所有三元组指数的最小距离,并丢弃其他指数。因此,通过上面的输入,我想要输出:

indicesOUT = 
array([[ 0,  0,  0],
       [ 2,  0,  2],
       [95, 71, 95]])

distancesOUT=
array([  0.98713981,  1.42340327,  74.84623217])

我目前的策略如下:

import numpy as np

indicesOUT = []
distancesOUT = []

for i in range(6):
    for j in range(6):
        for k in range(6):
            if len([s for s in indicesOUT if [i,j,k] == s]) == 0:
                current = np.array([i, j, k])
                ind = np.where((indices == current).all(-1) == True)[0]
                currentDistances = distances[ind]
                dist = np.amin(distances)
                indicesOUT.append([i, j, k])
                distancesOUT.append(dist)

问题是,实际的数组每个都有大约400万个元素,所以这种方法太慢了。这样做最有效的方法是什么?

1 个答案:

答案 0 :(得分:2)

这实际上是一个分组操作,并且NumPy没有针对它进行优化。幸运的是,Pandas软件包有一些非常快速的工具可以适应这个确切的问题。 根据您的数据,我们可以这样做:

import pandas as pd

def drop_duplicates(indices, distances):
    data = pd.Series(distances)
    grouped = data.groupby(list(indices.T)).min().reset_index()
    return grouped.values[:, :3], grouped.values[:, 3]

您的数据输出

array([[  0.,   0.,   0.],
       [  2.,   0.,   2.],
       [ 95.,  71.,  95.]]),
array([  0.98713981,   1.42340327,  74.84623217])

我的基准测试显示,对于4,000,000个元素,这应该在大约一秒钟内运行:

indices = np.random.randint(0, 100, size=(4000000, 3))
distances = np.random.random(4000000)
%timeit drop_duplicates(indices, distances)
# 1 loops, best of 3: 1.15 s per loop

如上所述,索引的输入顺序不一定会被保留;保持原始秩序需要更多的思考。