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

Python 从zip(a,b,c)计算所有按(a,b)元组分组的c的平均值的快速方法,python,python-2.7,numpy,Python,Python 2.7,Numpy,我有三个数组的dddaszip() 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值的平均值,

我有三个数组的
ddd
as
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

到目前为止,我只计算了
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)]

我也觉得我的单行本太长,难以阅读。在这里添加另一个要比较的层的快速且简单的阅读方式是什么

我建议您切换到使用来完成此任务,因为这样可以更简单地对行中的数据进行推理:

请注意,用
(aaa,bbb)
元组分组的行生成一个新的数据帧,然后询问其余列的平均值是多么简单

如果Pandas不是您的选项,那么还有一些附加项目可以提供多维数组分组功能,例如和

如果您想要一个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:这里有一个简单的方法-

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
并使用
数组切片
,因此可以更快-

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) )

ddd
中的所有元素是否都具有相同的长度?@Divakar您的意思是
aaa
bbb
ccc
具有相同的长度?是的,这就是我的意思。谢谢。@Divakar是的,它应该放在第一位。我编辑了我的问题。谢谢。您的问题描述令人困惑。您似乎希望对
(aaa,bbb)
对进行分组,并对每组进行平均。这与在该索引处获得
aaa==bbb
为真的
ccc
值的平均值不一样。但是如果我有很多对
aaa==bbb
,这种方法就行不通了?@Jan:为什么不行?并不是说“许多对”是一个足够清晰的问题描述,你正在尝试做什么。熊猫工作,非常感谢你。但Python2.7似乎没有统计数据。任何东西都可以取代它?@Jan:啊,我错了,
statistics
在Python 3中是新的。我将更新。对于
结果
,只需注意我使用了
np.mean(cs)
,它也可以工作。
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) )