我有一个形状(N,20,20)的numpy数组数据,N是一些非常大的数字。 我想获得每个20x20子阵列中唯一值的数量。 使用循环:
values = []
for i in data:
values.append(len(np.unique(i)))
我怎样才能对这个循环进行矢量化?速度是一个问题。
如果我尝试np.unique(数据),我得到整个数据数组的唯一值,而不是单独的20x20块,所以这不是我需要的。
答案 0 :(得分:3)
首先,您可以使用data.reshape(N,-1)
,因为您有兴趣对最后2个维度进行排序。
获取每行唯一值的简单方法是将每一行转储到一个集合中并让它进行排序:
[len(set(i)) for i in data.reshape(data.shape[0],-1)]
但这是一个迭代,可能是一个快速的。
'向量化'的一个问题是每行中唯一值的集合或列表的长度不同。 “矢量化”时,“具有不同长度的行”是一个红色标记。您不再具有“矩形”数据布局,使大多数矢量化成为可能。
您可以对每一行进行排序:
np.sort(data.reshape(N,-1))
array([[1, 2, 2, 3, 3, 5, 5, 5, 6, 6],
[1, 1, 1, 2, 2, 2, 3, 3, 5, 7],
[0, 0, 2, 3, 4, 4, 4, 5, 5, 9],
[2, 2, 3, 3, 4, 4, 5, 7, 8, 9],
[0, 2, 2, 2, 2, 5, 5, 5, 7, 9]])
但是如何在不迭代的情况下识别每行中的唯一值?计算非零差异的数量可能只是诀窍:
In [530]: data=np.random.randint(10,size=(5,10))
In [531]: [len(set(i)) for i in data.reshape(data.shape[0],-1)]
Out[531]: [7, 6, 6, 8, 6]
In [532]: sdata=np.sort(data,axis=1)
In [533]: (np.diff(sdata)>0).sum(axis=1)+1
Out[533]: array([7, 6, 6, 8, 6])
我打算添加关于浮点数的警告,但如果np.unique
适用于您的数据,我的方法应该也能正常工作。
[(np.bincount(i)>0).sum() for i in data]
这是一个迭代解决方案,明显快于我的len(set(i))
版本,并且与diff...sort
具有竞争力。
在[585]中:data.shape 出[585] :( 10000,400)
In [586]: timeit [(np.bincount(i)>0).sum() for i in data]
1 loops, best of 3: 248 ms per loop
In [587]: %%timeit
sdata=np.sort(data,axis=1)
(np.diff(sdata)>0).sum(axis=1)+1
.....:
1 loops, best of 3: 280 ms per loop
我刚刚找到了一种更快捷的方式来使用bincount
,np.count_nonzero
In [715]: timeit np.array([np.count_nonzero(np.bincount(i)) for i in data])
10 loops, best of 3: 59.6 ms per loop
我对速度提升感到惊讶。但后来我回忆起count_nonzero
用于其他函数(例如np.nonzero
)来为返回结果分配空间。所以有意义的是,这个函数将被编码以获得最大速度。 (它在diff...sort
情况下没有帮助,因为它不接受轴参数)。