
使用pd.pivot_table()时若只指定index和columns但未明确values参数,会导致结果仅保留索引而缺失列值与统计结果;正确做法是显式传入values(如辅助计数列)并配合aggfunc完成交叉频次统计。
使用`pd.pivot_table()`时若只指定`index`和`columns`但未明确`values`参数,会导致结果仅保留索引而缺失列值与统计结果;正确做法是显式传入`values`(如辅助计数列)并配合`aggfunc`完成交叉频次统计。
在 Pandas 中构建透视表(pivot table)时,一个常见误区是认为仅通过 index 和 columns 参数就能自动对行/列组合进行计数。实际上,pd.pivot_table() 是一个聚合导向的操作:它必须明确知道“对哪一列数据执行何种聚合”,否则无法生成数值型结果——这正是问题中“只有日期索引显示,列头和计数全为空”的根本原因。
pivot_table 的核心参数逻辑如下:
- index: 定义行标签(分组依据);
- columns: 定义列标签(另一维度分组);
- values: 必须指定——指明参与聚合的原始列(标量值);
- aggfunc: 指定聚合方式(如 "count"、"sum"、"size" 等)。
当原始 DataFrame 中没有适合直接聚合的数值列(例如本例仅有 'Date' 和 'Status' 两个分类字段),需人工添加一个可聚合的占位列(如全为 1 的计数辅助列),再将其作为 values 输入。
以下是完整、可复现的解决方案:
import pandas as pd
# 构建示例数据
df = pd.DataFrame({
'Date': ['2024-02-20', '2024-02-18', '2024-02-16', '2024-02-01',
'2024-02-20', '2024-01-21', '2024-02-20', '2024-01-21',
'2024-02-20', '2024-02-20', '2024-02-20'],
'Status': ['Won', 'Credit Pulled', 'Credit Pulled', 'Credit Pulled',
'Pre Credit Pull', 'Credit Pulled', 'Credit Pulled',
'Won', 'Awaiting Bank Account', 'Credit Pulled', 'Credit Pulled']
})
# ✅ 正确做法:添加辅助计数列,并显式指定 values
df['cnt'] = 1
df_pivot = pd.pivot_table(
data=df,
index='Date', # 行:日期
columns='Status', # 列:状态类型
values='cnt', # 关键!指定聚合目标列
aggfunc='count', # 对 cnt 列计数
fill_value=0 # 直接填充空值为 0(替代 fillna)
)
print(df_pivot)输出结果:
Status Awaiting Bank Account Credit Pulled Pre Credit Pull Won Date 2024-01-21 0 1 0 1 2024-02-01 0 1 0 0 2024-02-16 0 1 0 0 2024-02-18 0 1 0 0 2024-02-20 1 3 1 1
? 关键注意事项:
- ❌ 错误写法:pd.pivot_table(df, index='Date', columns='Status', aggfunc='count')
→ 因未指定 values,Pandas 尝试对所有数值列聚合,但本例无数值列,故返回空结构。 - ✅ 推荐替代:若仅需频次统计,可更简洁地使用 pd.crosstab():
pd.crosstab(df['Date'], df['Status'])
功能等价、语法更直观,且默认以整数呈现、无 NaN。
- fill_value=0 比 fillna(0) 更高效,应在 pivot_table() 内直接设置;
- 列名层级:当 values 为单列时,结果顶部会多出一层列名(如本例中的 'cnt');若需扁平化列名,可链式调用 .droplevel(0, axis=1)。
掌握 values 参数的必要性,是写出可靠透视表的第一步。记住:没有 values,就没有聚合值;没有聚合值,就没有真正的透视表。










