快速计算矩阵元素的出现次数

时间:2016-02-06 18:36:33

标签: python numpy

M n 分别为 d x d - 和 d - dimensonal numpy整数数组。我想计算形式(n(i),n(j),M(i,j))的三元组数。因此,我想要一个numpy数组,以便每个条目计算这种三元组的出现次数。

编辑: M 是对称的,我不想用i = j计算三元组。

我目前正在使用itertools.product(对所有对进行循环)和numpy.bincount来执行此操作,但速度太慢。有没有更聪明的方法,可能使用numpy

2 个答案:

答案 0 :(得分:1)

由于数组包含整数,因此可以将每个三元组视为线性索引元素。这是一种记住哲学的方法,从而避免了循环,如此 -

# Form n(i) x n(j) array and then append with "columnar" M(i,j) array
nn_arr = n[np.array(list(itertools.product(range(5), repeat=2)))]

nn_M_arr = np.concatenate((nn_arr,M.reshape(-1,1)),axis=1)

# Get linear indices version
dims = nn_M_arr.max(0)+1
lidx = np.ravel_multi_index(nn_M_arr.T,dims)

# Get unique indices and the counts
_, idx, counts = np.unique(lidx,return_index=True,return_counts=True)

# Get corresponding unique triplets using unique indices and zip with counts
out = zip(map(tuple,nn_M_arr[idx]),counts)

示例运行 -

In [206]: M
Out[206]: 
array([[1, 0, 0, 2, 0],
       [1, 1, 2, 0, 2],
       [0, 0, 2, 0, 1],
       [2, 1, 2, 0, 2],
       [1, 1, 1, 1, 0]])

In [207]: n
Out[207]: array([0, 1, 1, 1, 2])

In [208]: out
Out[208]: 
[((0, 0, 1), 1),
 ((0, 1, 0), 2),
 ((0, 1, 2), 1),
 ((0, 2, 0), 1),
 ((1, 0, 0), 1),
 ((1, 0, 1), 1),
 ((1, 0, 2), 1),
 ((1, 1, 0), 4),
 ((1, 1, 1), 2),
 ((1, 1, 2), 3),
 ((1, 2, 1), 1),
 ((1, 2, 2), 2),
 ((2, 0, 1), 1),
 ((2, 1, 1), 3),
 ((2, 2, 0), 1)]

答案 1 :(得分:1)

让:

M=np.random.randint(0,3,(10,10))
n=np.random.randint(0,3,10)

制作三元组并放弃i = j:

x,y=np.meshgrid(n,n)
a=np.dstack((x,y,M)).reshape(-1,3)
au=a[a [:,0]!=a[:,1]]   # i<>j

唯一的问题是它只使用一维数组。一个解决方案是转换字符串中的行:这确保了懒惰的比较,并且通常很快。

c=np.frombuffer(au,dtype='S12')   # 12 is  3*n.itemsize

_,indices,counts=np.unique(c,return_index=True,return_counts=True)

result=np.vstack((counts,au[indices].T)) # count first.

##
array([[1, 2, 5, 3, 4, 1, 4, 4, 3, 4, 9, 1, 3, 4, 9, 3, 4],
       [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2],
       [1, 1, 1, 2, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0, 1, 1, 1],
       [0, 1, 2, 0, 1, 2, 0, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]], dtype=int64)

如果整数像这里一样小(&lt; 4),你可以展示结果,以便res[n(i),n(j),M(i,j)]给出计数:

res=np.zeros((3,3,3),int) 
res[list(zip(*au[indices]))]=counts