我有一个Numpy结构化数组,按第一列排序:
x = array([(2, 3), (2, 8), (4, 1)], dtype=[('recod', '<u8'), ('count', '<u4')])
我需要合并记录(总结第二列的值)
x[n][0] == x[n + 1][0]
在这种情况下,所需的输出为:
x = array([(2, 11), (4, 1)], dtype=[('recod', '<u8'), ('count', '<u4')])
实现这一目标的最佳途径是什么?
答案 0 :(得分:3)
您可以使用np.unique
为第一列中的每个元素获取ID数组,然后使用np.bincount
根据ID在第二列元素上执行 accum积累 -
In [140]: A
Out[140]:
array([[25, 1],
[37, 3],
[37, 2],
[47, 1],
[59, 2]])
In [141]: unqA,idx = np.unique(A[:,0],return_inverse=True)
In [142]: np.column_stack((unqA,np.bincount(idx,A[:,1])))
Out[142]:
array([[ 25., 1.],
[ 37., 5.],
[ 47., 1.],
[ 59., 2.]])
您可以通过np.diff
和np.cumsum
的组合避免使用np.unique
,这可能会有所帮助,因为np.unique
也会在内部进行排序,在这种情况下不需要作为输入数据已经排序。实现看起来像这样 -
In [201]: A
Out[201]:
array([[25, 1],
[37, 3],
[37, 2],
[47, 1],
[59, 2]])
In [202]: unq1 = np.append(True,np.diff(A[:,0])!=0)
In [203]: np.column_stack((A[:,0][unq1],np.bincount(unq1.cumsum()-1,A[:,1])))
Out[203]:
array([[ 25., 1.],
[ 37., 5.],
[ 47., 1.],
[ 59., 2.]])
答案 1 :(得分:2)
pandas
使这种类型的"group-by" operation变得微不足道:
In [285]: import pandas as pd
In [286]: x = [(25, 1), (37, 3), (37, 2), (47, 1), (59, 2)]
In [287]: df = pd.DataFrame(x)
In [288]: df
Out[288]:
0 1
0 25 1
1 37 3
2 37 2
3 47 1
4 59 2
In [289]: df.groupby(0).sum()
Out[289]:
1
0
25 1
37 5
47 1
59 2
如果这是您需要的唯一操作,您可能不会想要对pandas的依赖,但是一旦开始,您可能会在库中找到其他有用的位。
答案 2 :(得分:2)
Dicakar's
以结构化数组形式回答:
In [500]: x=np.array([(25, 1), (37, 3), (37, 2), (47, 1), (59, 2)], dtype=[('recod', '<u8'), ('count', '<u4')])
查找唯一值并计算重复项:
In [501]: unqA, idx=np.unique(x['recod'], return_inverse=True)
In [502]: cnt = np.bincount(idx, x['count'])
制作一个新的结构化数组并填写字段:
In [503]: x1 = np.empty(unqA.shape, dtype=x.dtype)
In [504]: x1['recod'] = unqA
In [505]: x1['count'] = cnt
In [506]: x1
Out[506]:
array([(25, 1), (37, 5), (47, 1), (59, 2)],
dtype=[('recod', '<u8'), ('count', '<u4')])
有一个recarray
函数可以从数组列表中构建一个数组:
In [507]: np.rec.fromarrays([unqA,cnt],dtype=x.dtype)
Out[507]:
rec.array([(25, 1), (37, 5), (47, 1), (59, 2)],
dtype=[('recod', '<u8'), ('count', '<u4')])
在内部它做同样的事情 - 构建一个正确大小和dtype的空数组,然后遍历dtype字段。重新排列只是专用数组子类包装器中的结构化数组。
有两种填充结构化数组的方法(特别是使用不同的dtype) - 使用x
和逐字段的元组列表。
答案 3 :(得分:1)
您可以使用np.reduceat
。您只需要填充x[:, 0]
更改的位置,这些更改相当于将np.diff(x[:,0])
的非零索引移位一加上初始索引0:
>>> i = np.r_[0, 1 + np.nonzero(np.diff(x[:,0]))[0]]
>>> a, b = x[i, 0], np.add.reduceat(x[:, 1], i)
>>> np.vstack((a, b)).T
array([[25, 1],
[37, 5],
[47, 1],
[59, 2]])