让 M 和 n 分别为 d x d - 和 d - dimensonal numpy整数数组。我想计算形式(n(i),n(j),M(i,j))的三元组数。因此,我想要一个numpy数组,以便每个条目计算这种三元组的出现次数。
编辑: M 是对称的,我不想用i = j计算三元组。
我目前正在使用itertools.product
(对所有对进行循环)和numpy.bincount
来执行此操作,但速度太慢。有没有更聪明的方法,可能使用numpy
?
答案 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