将bincount应用于2D numpy数组的每一行

4
有没有办法使用“axis = 1”应用bincount?期望的结果与列表理解相同:
import numpy as np
A = np.array([[1,0],[0,0]])
np.array([np.bincount(r,minlength = np.max(A) + 1) for r in A])

#array([[1,1]
#       [2,0]])

2
一个2013年的问题:numpy的bincount能够处理二维数组吗?:https://dev59.com/HmIk5IYBdhLWcg3wg-fK - hpaulj
啊,谢谢你提供的信息,我之前不知道有apply_along_axis这个函数...不过很遗憾,对于大矩阵它似乎表现不佳,在我的数据上,下面的最佳答案在下面的示例上需要10.1秒,我猜测apply函数并没有被很好地优化... - maxymoo
如果每行中的值都是唯一的(相对于其他行),您可以将平坦的数组进行“bincount”,然后分离计数。您可以通过添加适当大的偏移量使值唯一。 - hpaulj
1
apply_along_axis 并不是那么神奇。看看它的代码,它只是一种花哨的循环形式。 - hpaulj
3
这是一个添加了你所询问的 NumPy 功能的拉取请求 链接。由于觉得这个功能增加了代码复杂度,但实际价值不高,因此它从未被合并。 - Jaime
显示剩余2条评论
3个回答

5

np.bincount 在某个轴上不适用于 2D 数组。为了通过单个向量化调用 np.bincount 来获得所需的效果,可以创建一个 ID 的一维数组,使得即使元素相同,不同行也会有不同的 ID。这将保持来自不同行的元素在使用带有这些 ID 的单个调用 np.bincount 时不会一起分组。因此,可以考虑使用 linear indexing 的思想来创建这样的 ID 数组,如下所示 -

N = A.max()+1
id = A + (N*np.arange(A.shape[0]))[:,None]

然后,将这些ID提供给np.bincount,最后重新调整为2D -
np.bincount(id.ravel(),minlength=N*A.shape[0]).reshape(-1,N)

3
您可以使用apply_along_axis,这里是一个例子。
import numpy as np
test_array = np.array([[0, 0, 1], [0, 0, 1]])
print(test_array)
np.apply_along_axis(np.bincount, axis=1, arr= test_array,
                                          minlength = np.max(test_array) +1)

注意,该数组的最终形状取决于箱子的数量,同时您可以在apply_along_axis之外指定其他参数。

2
如果数据太大而无法高效处理,则问题更可能是密集矩阵的内存使用而非数值运算本身。以下是一个示例,演示如何在矩阵过大以至于无法使用“bincounts”方法时,使用sklearn Hashing Vectorizer(结果为稀疏矩阵):
import numpy as np
from sklearn.feature_extraction.text import HashingVectorizer
h = HashingVectorizer()
A = np.random.randint(100,size=(1000,100))*10000
A_str = [" ".join([str(v) for v in i]) for i in A]

%timeit h.fit_transform(A_str)
#10 loops, best of 3: 110 ms per loop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接