我有ddd
作为三个数组的zip()
;
aaa = np.array([1, 1, 1, 1, 3, 2])
bbb = np.array([10, 10, 2, 2, 3, 2])
ccc = np.array([5, 15, 9, 11, 20, 10])
ddd = zip(aaa, bbb, ccc)
我希望ccc
中的元素的平均值按照aaa
和bbb
中相同索引处的元素进行分组。在上面的示例中,有两个ccc
值,其对应的(aaa, bbb)
对为(1, 10)
,因此我想要两个ccc
值的平均值,即5和15。 / p>
到目前为止,我只设法计算ccc
的值bbb
的平均值是否相同:
>>> [(chosenb, np.mean([cc for aa,bb,cc in ddd if bb==chosenb])) for chosenb in set([b for a,b,c in ddd])]
[(10, 10.0), (3, 20.0), (2, 10.0)]
预期答案是
[(1, 10, 10.0), (1, 2, 10.0), (3, 3, 20.0), (2, 2, 10.0)]
我也觉得我的单行方式太长而且难以阅读。如何快速,简单地添加另一个层来进行比较?
答案 0 :(得分:6)
我建议您切换到使用Pandas执行此任务,因为它可以更简单地推断行中的数据:
>>> import pandas as pd
>>> df = pd.DataFrame({'aaa': aaa, 'bbb': bbb, 'ccc': ccc})
>>> df.groupby(['aaa', 'bbb'], as_index=False).mean()
aaa bbb ccc
0 1 2 10
1 1 10 10
2 2 2 10
3 3 3 20
请注意,生成一个包含(aaa, bbb)
元组的行的新数据帧是多么简单,然后询问其余列的平均值。
如果Pandas不适合您,还有一些附加项目可以提供numpy
多维数组分组功能,例如numpy-indexed
和numpy-groupies
。< / p>
如果您想要一个Python解决方案,您必须首先使用字典对值进行分组:
grouped = {}
for a, b, c in zip(aaa, bbb, ccc):
grouped.setdefault((a, b), []).append(c)
result = [(a, b, np.mean(cs)) for (a, b), cs in grouped.items()]
答案 1 :(得分:2)
方法#1:这是一种NumPy方式 -
from __future__ import division # make sure divisions result in float
# Get unique scalar mappings for each group from aaa and bbb
idx = aaa*(bbb.max()-bbb.min()+1) + bbb
# For each group, get start indices, unique tags and counts
st,tags,c = np.unique(idx, return_index=1, return_counts=1, return_inverse=1)[1:]
# Finally use bincount to get grouped summations and then divide by the counts
# for grouped mean values. Zip for desired output format.
out = zip(aaa[st], bbb[st], np.bincount(tags, ccc)/c)
示例输入,输出 -
In [189]: aaa = np.array([1, 1, 1, 1, 3, 2])
...: bbb = np.array([10, 10, 2, 2, 3, 2])
...: ccc = np.array([5, 15, 9, 11, 20, 10])
...:
In [191]: out
Out[191]: [(1, 2, 10.0), (1, 10, 10.0), (2, 2, 10.0), (3, 3, 20.0)]
方法#2:这是另一个避免np.unique
并使用array-slicing
的方法,因此可能更快 -
idx = np.lexsort([aaa,bbb])
a0 = aaa[idx]
b0 = bbb[idx]
c0 = ccc[idx]
m = np.concatenate(([True], (a0[1:] != a0[:-1]) | (b0[1:] != b0[:-1]) ))
tags = m.cumsum()-1
out = zip(a0[m], b0[m], np.bincount(tags, c0)/np.bincount(tags) )