Python 具有条件的每行唯一值的二维矢量化
考虑如下所示的数组和函数定义:Python 具有条件的每行唯一值的二维矢量化,python,arrays,numpy,Python,Arrays,Numpy,考虑如下所示的数组和函数定义: import numpy as np a = np.array([[2, 2, 5, 6, 2, 5], [1, 5, 8, 9, 9, 1], [0, 4, 2, 3, 7, 9], [1, 4, 1, 1, 5, 1], [6, 5, 4, 3, 2, 1], [3, 6, 3, 6, 3, 6],
import numpy as np
a = np.array([[2, 2, 5, 6, 2, 5],
[1, 5, 8, 9, 9, 1],
[0, 4, 2, 3, 7, 9],
[1, 4, 1, 1, 5, 1],
[6, 5, 4, 3, 2, 1],
[3, 6, 3, 6, 3, 6],
[0, 2, 7, 6, 3, 4],
[3, 3, 7, 7, 3, 3]])
def grpCountSize(arr, grpCount, grpSize):
count = [np.unique(row, return_counts=True) for row in arr]
valid = [np.any(np.count_nonzero(row[1] == grpSize) == grpCount) for row in count]
return valid
该函数的作用是返回数组a
中的行,这些行具有完全相同的grpCount
元素组,每个元素组包含完全相同的grpSize
例如:
# which rows have exactly 1 group that holds exactly 2 identical elements?
out = a[grpCountSize(a, 1, 2)]
正如预期的那样,代码输出out=[[2,2,5,6,2,5],[3,3,7,7,3,3]]
。
第一个输出行正好有一组2(即:5,5),而第二个输出行也正好有一组2(即:7,7)
同样地:
# which rows have exactly 2 groups that each hold exactly 3 identical elements?
out = a[grpCountSize(a, 2, 3)]
这将产生out=[[3,6,3,6,3,6]]
,因为只有此行有两个组,每个组正好包含3个元素(即:3,3,3和6,6,6)
问题:我的实际数组只有6列,但它们可能有数百万行。代码完全按照预期工作,但对于长数组来说速度非常慢。有什么方法可以加快速度吗?
np.unique
对数组进行排序,从而降低您的使用效率。使用np.bincount
,这样很可能会节省一些时间(取决于数组的形状和值)。您也不再需要np.任何:
def grpCountSize(arr, grpCount, grpSize):
count = [np.bincount(row) for row in arr]
valid = [np.count_nonzero(row == grpSize) == grpCount for row in count]
return valid
另一种可能节省更多时间的方法是为所有行使用相同数量的存储箱,并创建一个数组:
def grpCountSize(arr, grpCount, grpSize):
m = arr.max()
count = np.stack([np.bincount(row, minlength=m+1) for row in arr])
return (count == grpSize).sum(1)==grpCount
另一个升级是使用。例如(请注意,上面帖子中测试的Numba解决方案速度更快。我只是提供了numpy解决方案作为示例。您可以使用上面链接的帖子中建议的任何函数替换该函数):
以上所有解决方案的输出:
a[grpCountSize2(a, 1, 2)]
#array([[2, 2, 5, 6, 2, 5],
# [3, 3, 7, 7, 3, 3]])
numpy
中的巨大加速来自于对整个数组应用编译方法。你的代码必须一行一行地工作;如果您无法找到一种同时处理多行的方法,那么您必须尝试加快逐行操作的速度。我怀疑您可以将unique
和count
操作一起应用于一行,但没有意识到与当前的两个循环相比,than是否会提高时间。另一个选项是使用numba
,但我不会对此进行探讨。非常清楚和详细的解释!我是Python新手,还没有尝试过实现NUBA,但我认为这对我来说是值得研究的。如果您只是想使用NUBA而不想深入了解其细节,只需在提供的链接中用任何NUBA函数替换bincount2D\u矢量化的
。
a[grpCountSize2(a, 1, 2)]
#array([[2, 2, 5, 6, 2, 5],
# [3, 3, 7, 7, 3, 3]])