对含两个分类变量的DataFrame执行groupby并统计唯一组合数的问题
嘿,我来帮你搞定这个分组计数的问题!先理清楚你的场景和遇到的问题:
你的场景
你有这样一个数据集:
body-style make 0 convertible alfa-romeo 1 convertible alfa-romeo 2 hatchback alfa-romeo 3 sedan audi 4 sedan audi
想要按make和body-style的唯一组合统计数量,得到这样的结果:
make body-style count 0 alfa-romero convertible 2 1 alfa-romero hatchback 1 2 audi sedan 2
你尝试的代码是:
body = pd.DataFrame({'make':['alfa-romeo','alfa-romeo','alfa-romeo','audi','audi'], 'body-style':['convertible','convertible','hatchback','sedan','sedan']}) body.groupby(by=['make','body-style'], as_index=False).count()
但遇到了list index out of range的错误,移除其中一个分组列或者去掉as_index=False能运行,但结果不符合需求,你不想用新增全1列再sum的方法,想要更简洁的实现。
问题出在哪?
当你用groupby(..., as_index=False).count()的时候,因为你的DataFrame里只有make和body-style两列,而这两列都被你用作分组键了,count()函数会尝试统计每个分组里非分组列的非空值数量,但此时根本没有其他列可以统计,所以就触发了这个错误。
几个简洁的解决方案
这里有三种直接的方法,都不需要新增额外列:
方法1:用size()(最推荐)
size()是Pandas专门用来统计分组行数的方法,不管你有没有其他列,它都能直接返回每组的数量,搭配as_index=False再重命名列就行:
body.groupby(by=['make','body-style'], as_index=False).size().rename(columns={'size': 'count'})
这个方法逻辑最清晰,完全贴合你的需求,一步到位。
方法2:用value_counts()快速统计
如果你的需求就是统计两列的所有唯一组合数量,value_counts()更简单,它会直接给出所有组合的计数,之后转成DataFrame调整结构即可:
pd.DataFrame(body.value_counts()).reset_index().rename(columns={0: 'count'})
value_counts()返回的是一个Series,索引是组合对,值是数量,reset_index()把索引转成普通列,再把默认的列名0改成count就完美了。
方法3:用agg()指定计数列
也可以用agg()方法,明确指定用某一列(比如make)来计数,这样即使所有列都是分组键也不会出错:
body.groupby(by=['make','body-style'], as_index=False).agg(count=('make', 'count'))
这里用agg()的字典语法,直接生成名为count的列,用make列的count()方法统计行数,结果和前两种一致。
最终效果
以上三种方法都能得到你想要的输出:
make body-style count 0 alfa-romeo convertible 2 1 alfa-romeo hatchback 1 2 audi sedan 2
内容的提问来源于stack exchange,提问作者Justin

