我有一个像这样的numpy数组:
print(*a, sep='\n')
我想要做的是平均每个重复的第一项的行数。在此示例中,对第一行和第三行的第二到最后一列取平均。正确的输出应为:
1
2
3
4
这个答案Average entries with duplicate first element in 2D numpy array与我想做的事情非常相关。
答案 0 :(得分:3)
这是一种方法:
l = [np.argwhere(i==a[:,0]).ravel() for i in np.unique(a[:,0])]
np.array([a[i].mean(axis=0).tolist() for i in l])
array([[1., 3., 4., 5.],
[2., 2., 3., 4.],
[3., 2., 3., 4.]])
说明
关于第一个列表的理解,np.arwhere
将为每个unique
元素返回一个数组,该数组的行的索引具有相同的第一个元素
l = [np.argwhere(i==a[:,0]).ravel() for i in np.unique(a[:,0])]
[array([0, 2]), array([1]), array([3])]
现在,您只需要根据a
中的每个数组对l
进行切片,并用以下方法求平均值:
np.array([a[i].mean(axis=0).tolist() for i in l])
array([[1., 3., 4., 5.],
[2., 2., 3., 4.],
[3., 2., 3., 4.]])
答案 1 :(得分:2)
你可以用熊猫吗?
import pandas as pd
df = pd.DataFrame(
[[1, 2, 3, 4],
[2, 2, 3, 4],
[1, 4, 5, 6],
[3, 2, 3, 4]],
columns=list('abcd')
)
df.groupby('a').mean().reset_index().values
# returns:
array([[1, 3, 4, 5],
[2, 2, 3, 4],
[3, 2, 3, 4]], dtype=int64)
答案 2 :(得分:1)
方法1
这是NumPy的矢量化-
def groupby_mean(a):
# Sort array by groupby column
b = a[a[:,0].argsort()]
# Get interval indices for the sorted groupby col
idx = np.flatnonzero(np.r_[True,b[:-1,0]!=b[1:,0],True])
# Get counts of each group and sum rows based on the groupings & hence averages
counts = np.diff(idx)
avg = np.add.reduceat(b[:,1:],idx[:-1],axis=0)/counts.astype(float)[:,None]
# Finally concatenate for the output in desired format
return np.c_[b[idx[:-1],0],avg]
方法2
另一个向量化了一个利用matrix-multiplication
-
def groupby_mean_matmul(a):
unq = np.unique(a[:,0])
m = a[:,0,None] == unq
return np.c_[unq, m.T.dot(a[:,1:])/m.sum(0)[:,None].astype(float)]
样品运行-
In [51]: a
Out[51]:
array([[1, 2, 3, 4],
[2, 2, 3, 4],
[1, 4, 5, 6],
[3, 2, 3, 4]])
In [52]: groupby_mean(a)
Out[52]:
array([[1., 3., 4., 5.],
[2., 2., 3., 4.],
[3., 2., 3., 4.]])