Python 熊猫:聚合后在分组键上加入 我所拥有的
我有这样一个熊猫架:Python 熊猫:聚合后在分组键上加入 我所拥有的,python,pandas,pandas-groupby,Python,Pandas,Pandas Groupby,我有这样一个熊猫架: df1 = pd.DataFrame({ 'date': ['31-05-2017', '31-05-2017', '31-05-2017', '31-05-2017', '01-06-2017', '01-06-2017'], 'tag': ['A', 'B', 'B', 'B', 'A', 'A'], 'metric1': [0, 0, 0, 1, 1, 1], 'metric2': [0, 1, 1, 0, 1, 0] })
df1 = pd.DataFrame({
'date': ['31-05-2017', '31-05-2017', '31-05-2017', '31-05-2017', '01-06-2017', '01-06-2017'],
'tag': ['A', 'B', 'B', 'B', 'A', 'A'],
'metric1': [0, 0, 0, 1, 1, 1],
'metric2': [0, 1, 1, 0, 1, 0]
})
df2 = pd.DataFrame({
'date': ['31-05-2017', '31-05-2017', '01-06-2017'],
'tag': ['A', 'B', 'A'],
'metric3': [25, 3, 7,]
})
我想要什么
1) 我想对日期
和标记
date | tag | metric1_sum | metric2_sum | metric2_percentage| metric 3
-----------|-----|-------------|-------------|-------------------|---------
31-05-2017 | A | 0 | 0 | 0 | 25
31-05-2017 | B | 1 | 2 | 0.667 | 3
01-06-2017 | A | 1 | 0 | 0.5 | 7
2) 计算metric_2
3) 将分组的df1与df2合并,以便我对每个日期
和标记
date | tag | metric1_sum | metric2_sum | metric2_percentage| metric 3
-----------|-----|-------------|-------------|-------------------|---------
31-05-2017 | A | 0 | 0 | 0 | 25
31-05-2017 | B | 1 | 2 | 0.667 | 3
01-06-2017 | A | 1 | 0 | 0.5 | 7
尝试
(1) 集体和集体工作
(2) 计算百分比是可行的,但将其作为列添加则不行
我用这个方法来计算百分比
>>> g2 = df1.groupby(['date', 'tag']).agg({'metric2': 'sum'})
>>> g2.groupby(level=0).apply(lambda x: x/float(x.sum()))
metric2
date tag
01-06-2017 A 1.0
31-05-2017 A 0.0
B 1.0
cols = ['date', 'tag']
d1 = df1.groupby(cols).agg(
dict(metric1='sum', metric2=['sum', 'mean'])
)
d1.columns = d1.columns.map('_'.join)
d1.join(df2.set_index(cols))
date tag metric1_sum metric2_sum metric2_mean metric3
0 01-06-2017 A 2 1 0.500000 7
1 31-05-2017 A 0 0 0.000000 25
2 31-05-2017 B 1 2 0.666667 3
但是,我现在如何将此分组的metric2
分配给我的组g
或我的df1
中的列metric2\u百分比
(3) 合并失败
与集团合并显然不起作用:
>>> pd.merge(g, df2, how='left', on=['date', 'tag'])
KeyError: 'date'
然后如何将
df1
减少到每组一行,以便将其与df2
合并?g
将日期、标记作为索引,而合并
需要列,您需要在g
上重置索引:
pd.merge(g.reset_index(), df2, how='left', on=['date', 'tag'])
或者指定left\u index=True
:
pd.merge(g, df2, how='left', left_index=True, right_on=['date', 'tag'])
两者的结果如下(列顺序略有不同):
这里有一个替代方案,可以通过减少一个连接来完成您的工作:
(df1.groupby(['date', 'tag']).apply(
lambda g: pd.Series({'metric1_sum': g.metric1.sum(),
'metric2_sum': g.metric2.sum(),
'metric2_percentage': g.metric2.mean()})
# assumed here you have only 1 and 0 in metric 2 column if not use your own lambda function
).reset_index().merge(df2, how='left', on=['date', 'tag']))
# date tag metric1_sum metric2_percentage metric2_sum metric3
#0 01-06-2017 A 2.0 0.500000 1.0 7
#1 31-05-2017 A 0.0 0.000000 0.0 25
#2 31-05-2017 B 1.0 0.666667 2.0 3
使用agg
<代码>1和0的平均值将与百分比相同
>>> g2 = df1.groupby(['date', 'tag']).agg({'metric2': 'sum'})
>>> g2.groupby(level=0).apply(lambda x: x/float(x.sum()))
metric2
date tag
01-06-2017 A 1.0
31-05-2017 A 0.0
B 1.0
cols = ['date', 'tag']
d1 = df1.groupby(cols).agg(
dict(metric1='sum', metric2=['sum', 'mean'])
)
d1.columns = d1.columns.map('_'.join)
d1.join(df2.set_index(cols))
date tag metric1_sum metric2_sum metric2_mean metric3
0 01-06-2017 A 2 1 0.500000 7
1 31-05-2017 A 0 0 0.000000 25
2 31-05-2017 B 1 2 0.666667 3
为了一艘班轮而过度设计
from collections import OrderedDict
df1.groupby(['date', 'tag']).agg(
dict(metric1='sum', metric2=['sum', 'mean'])
).pipe(
lambda d: pd.DataFrame(OrderedDict({'_'.join(k): v for k, v in d.iteritems()}))
).join(df2.set_index(['date', 'tag'])).reset_index()
date tag metric1_sum metric2_sum metric2_mean metric3
0 01-06-2017 A 2 1 0.500000 7
1 31-05-2017 A 0 0 0.000000 25
2 31-05-2017 B 1 2 0.666667 3
你能解释一下计算%和合并之间的问题吗?这些是独立的问题吗?太好了,我没有意识到我可以用reset_index()将组扁平化