从zip(a,b,c)计算(a,b)元组的所有c的平均值的快速方法

时间:2017-10-05 06:46:20

标签: python python-2.7 numpy

我有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中的元素的平均值按照aaabbb中相同索引处的元素进行分组。在上面的示例中,有两个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)]

我也觉得我的单行方式太长而且难以阅读。如何快速,简单地添加另一个层来进行比较?

2 个答案:

答案 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-indexednumpy-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) )