You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无需迭代统计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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 05:37:42