如果这是一个骗子,请引导。我checked到questions来了一些close,但不能解决我的问题。
我有一个虚拟的DataFrame
,如下所示:
grp Ax Bx Ay By A_match B_match
0 foo 3 2 2 2 False True
1 foo 2 1 1 0 False False
2 foo 4 3 0 3 False True
3 foo 4 3 1 4 False False
4 foo 4 4 3 0 False False
5 bar 3 0 3 0 True True
6 bar 3 4 0 3 False False
7 bar 1 2 1 2 True True
8 bar 1 3 4 1 False False
9 bar 1 1 0 3 False False
我的目标是比较A
和B
的列,并按grp
总结结果,从而:
A_match B_match
False True False True
grp
bar 3 2 3 2
foo 5 0 3 2
因此,我如下添加了两个_match
列,以获取上面的df
:
df['A_match'] = df['Ax'].eq(df['Ay'])
df['B_match'] = df['Bx'].eq(df['By'])
根据我的理解,我希望可以做这样的事情,但是不起作用:
df.groupby('grp')[['A_match', 'B_match']].agg(pd.Series.value_counts)
# trunc'd Traceback:
# ... ValueError: no results ...
# ... During handling of the above exception, another exception occurred: ...
# ... ValueError: could not broadcast input array from shape (5,7) into shape (5)
在我的实际数据中,我能够通过以一种不太令人满意的方式强迫_match
为pd.Categorical
来回避这一点。但是,我已经注意到成功与失败的关系,即使使用了这个伪数据,即使使用pd.Categorial
,我也仍然得到如上所述的确切错误:
df['A_match'] = pd.Categorical(df['Ax'].eq(df['Ay']).values, categories=[True, False])
df['B_match'] = pd.Categorical(df['Bx'].eq(df['By']).values, categories=[True, False])
df.groupby('grp')[['A_match', 'B_match']].agg(pd.Series.value_counts)
# ... ValueError: could not broadcast input array from shape (5,7) into shape (5)
对我来说毫无意义-形状(5,7)甚至从哪里来?我上次检查时,每个agg
都会通过形状(5,)
。而且甚至agg
的运行似乎也与我想象的不同,它应该与Series
相对:
>>> df.groupby('grp')[['A_match', 'B_match']].agg(lambda x: type(x))
A_match B_match
grp
bar <class 'pandas.core.series.Series'> <class 'pandas.core.series.Series'>
foo <class 'pandas.core.series.Series'> <class 'pandas.core.series.Series'>
# Good - it's Series, I should be able to call value_counts directly?
>>> df.groupby('grp')[['A_match', 'B_match']].agg(lambda x: x.value_counts())
# AttributeError: 'DataFrame' object has no attribute 'value_counts' <-- ?!?!? Where did 'DataFrame' come from?
我最终能够使用以下组合,但由于引入了许多不必要的axis
名称,因此仍然不能令人满意。
>>> df.melt(id_vars='grp', value_vars=['A_match', 'B_match']).reset_index().pivot_table(index='grp', columns=['variable', 'value'], aggfunc=pd.Series.count)
index
variable A_match B_match
value False True False True
grp
bar 3 2 3 2
foo 5 0 3 2
这两种方法似乎都非常想实现某些应该相对通用的用法。我想我的问题是,我是否忽略了这里明显的内容?
答案 0 :(得分:3)
您可以在字典上agg
:
(df.groupby('grp').agg({'A_match':'value_counts',
'B_match':'value_counts'})
.unstack(-1, fill_value=0)
)
输出:
A_match B_match
False True False True
bar 3.0 2.0 3 2
foo 5.0 NaN 3 2