如何无需迭代统计Pandas多列指定值出现次数并生成新DataFrame
问题:统计指定标签在DataFrame各列的出现次数
原始DataFrame如下:
import pandas as pd df = pd.DataFrame({'2012':['A','A','B','A'],'2013':['A','B','C','C'],'2014':['A','C','Z','C']})
输出:
2012 2013 2014 0 A A A 1 A B C 2 B C Z 3 A C C
需要生成目标DataFrame,统计**指定标签(A、B、C,不含Z)**在每列的出现次数,将标签设为索引展示各年份统计结果:
2012 2013 2014 A 3 1 1 B 1 1 0 C 0 2 2
已实现的迭代方案:
indexes = ['A','B','C'] df2 = pd.DataFrame(index=indexes, columns=df.columns, dtype=int) for idx in indexes: df2.loc[idx] = (df == idx).sum()
该方案可得到所需结果,但希望找到无需迭代、一次性实现的方法。尝试过value_counts()、pivot_table()和groupby()均未成功,搜索到的方案仅针对单列统计。
无需迭代的解决方案
方法1:apply+value_counts+reindex
对每列调用value_counts统计次数,再重新索引保留指定标签,缺失值补0:
target_labels = ['A', 'B', 'C'] result = df.apply(pd.Series.value_counts).reindex(target_labels).fillna(0).astype(int) print(result)
输出与目标一致。
方法2:melt+crosstab
先将宽表转长表并过滤无关标签,再用交叉表统计计数:
target_labels = ['A', 'B', 'C'] # 转换为长格式并过滤Z melted = df.melt(var_name='year', value_name='label').query('label in @target_labels') # 生成交叉表并补全索引 result = pd.crosstab(melted['label'], melted['year']).reindex(target_labels).fillna(0).astype(int) print(result)
方法3:stack+value_counts+unstack
通过堆叠数据统一统计,再重新调整结构:
target_labels = ['A', 'B', 'C'] result = df.stack().value_counts().unstack(level=0, fill_value=0).T.reindex(target_labels).astype(int) print(result)
内容的提问来源于stack exchange,提问作者nicobar
相关产品推荐
相关产品推荐

