我有一个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万个元素,所以这种方法太慢了。这样做最有效的方法是什么?
答案 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
如上所述,索引的输入顺序不一定会被保留;保持原始秩序需要更多的思考。