我想使用bincount
对数组求和,但它只支持双精度数。
例如,这有效:
np.bincount([1, 1, 0],weights=np.array([1, 2, 4]))
Out: array([ 4., 3.])
但是我想使用维度2数组:
np.bincount([1, 1, 0],weights=np.array([[1,1], [2,2], [4,4]]))
ValueError: object too deep for desired array
所需的输出是:
Out: array([[ 4., 4.],[3., 3.]])
评论后更好的解释:
我想将数组的每一行加到相应的索引中。
循环将是:
Bin=np.zeros(2,2)
for i in [1,1,0]:
Bin[i]+=a[i]
a是之前的3x2矩阵 有没有一种有效的方法来获得这个结果?
答案 0 :(得分:3)
根据numpy文档:
numpy.bincount(x, weights=None, minlength=None)
权重:array_like,可选; 权重,与x相同形状的数组。
所以你不能以这种方式直接使用bincount
,除非你以某种方式改变x
。
编辑:所以我提出了一个稍微有点棘手的方法,但是当你去大型数组时,无法保证性能。基本上我将利用scipy稀疏矩阵处理相同索引处的重复条目(它们求和):
from scipy.sparse import *
a = np.array([[1,1], [2,2], [4,4]])
ii = np.array([1, 1, 0])
ares = a.reshape((-1,),order='F')
# ares == array([1, 2, 4, 1, 2, 4])
col = np.tile(ii,(a.shape[1],))
# col == np.array([1, 1, 0, 1, 1, 0])
row = np.tile([0,1],(a.shape[0],1)).reshape((-1,),order='F')
# row == np.array([0,0,0,1,1,1])
g = coo_matrix((ares,(col,row)),shape=(2,2))
print g.todense()
现在,您必须将此概括为您的精确数据。基本思想是你想要将每个数据点映射到结果数组的正确元素,然后让稀疏数组处理对重复条目的求和。
否则,如果你被迫使用循环来解决这个问题,我会考虑使用Cython。
编辑2:对于踢球,我计时两种不同的方法:
import numpy as np
from scipy.sparse import *
def method1():
return np.array([np.bincount(ii, r) for r in a.T]).T
def method2():
ares = a.reshape((-1,),order='F')
col = np.tile(ii,(a.shape[1],))
row = np.tile(np.arange(a.shape[1]),(a.shape[0],1)).reshape((-1,),order='F')
return coo_matrix((ares,(col,row)),shape=(np.unique(ii).size,a.shape[1])).todense()
if __name__ == '__main__':
from timeit import Timer
a = np.random.randint(0,1000,(1000000,3))
ii = np.random.randint(0,10,(a.shape[0],))
N = 100
t1 = Timer("method1()", "from __main__ import method1")
t2 = Timer("method2()", "from __main__ import method2")
print 't2/t1: %f' % (t2.timeit(N)/t1.timeit(N))
在我的机器上,method2
比method1
慢约3-5倍,具体取决于输入的形状,因此循环不一定是不好的选择。
答案 1 :(得分:1)
我认为这是基于bincount的更简单的版本。本质上,您要按列划分权重,以使其具有与初始数组相同的大小,然后将不同的列堆叠在一起。
a = np.array([1, 1, 0])
b = np.array([[1,1], [2,2], [4,4]])
uni = np.unique(a)
a_x = np.bincount(a, weights=b[:,0], minlength=len(uni))
a_y = np.bincount(a, weights=b[:,1], minlength=len(uni))
final = np.column_stack((a_x.T, a_y.T))
# final = np.array([[ 4., 4.],[3., 3.]])
答案 2 :(得分:0)
您应该使用scipy csr
矩阵表示索引,然后使用点积与数据。在我的笔记本电脑上,大型矩阵的速度比@JoshAdel的method1
快14倍,比@JoshAdel的method2
快54倍。
def method1():
return np.array([np.bincount(ii, r) for r in a.T]).T
def method2():
ares = a.reshape((-1,),order='F')
col = np.tile(ii,(a.shape[1],))
row = np.tile(np.arange(a.shape[1]),(a.shape[0],1)).reshape((-1,),order='F')
return coo_matrix((ares,(col,row)),shape=(ii.max()+1,a.shape[1])).todense()
def method3():
csr = csr_matrix((np.ones(ii.shape[0]), (ii, np.arange(ii.shape[0]))))
return csr*a
让我们生成随机数据并为其计时:
n = 1<<18
d = 512
ii = np.random.randint(low=1, high=1<<10, size=n)
a = np.random.randn((n, d))
%timeit method1()
# 1 loop, best of 3: 3.13 s per loop
%timeit method2()
# 1 loop, best of 3: 11.7 s per loop
%timeit method3()
# 1 loop, best of 3: 216 ms per loop
# sanity checks:
assert (method1() == method2()).all()
assert (method1() == method3()).all()
注意:我将np.unique(ii).size
中的method2
替换为ii.max()+1