
本文介绍如何对含非数值首列(如国家名)的 DataFrame,按行计算数值列均值并填充该行中的 NaN 值,避免因类型混杂导致 mean() 报错,并提供可直接运行的 Pandas 实现方案。
本文介绍如何对含非数值首列(如国家名)的 dataframe,按行计算数值列均值并填充该行中的 nan 值,避免因类型混杂导致 `mean()` 报错,并提供可直接运行的 pandas 实现方案。
在实际数据处理中,常遇到类似如下结构的表格:首列为字符串标识(如国家、ID、类别名),后续多列为数值型年份数据,但存在缺失值(NaN)。此时若直接调用 df.mean(axis=1) 或 df.fillna(...),Pandas 会因混合数据类型(object + float64/int64)而报错或返回 NaN,无法正确计算行均值。
解决核心在于:跳过非数值列,仅对目标数值列子集执行行内均值计算与填充。推荐使用 df.apply(..., axis=1) 配合自定义 lambda 函数,精准控制每行参与计算的列范围。
以下是一个完整、健壮的实现示例:
import pandas as pd
import numpy as np
# 构造示例数据(模拟原始问题结构)
data = {
'Index': [0, 1, 2],
'Country': ['US', 'Germany', 'Japan'],
'1990': [5, 5, 9],
'1995': [6, np.nan, np.nan],
'2000': [np.nan, 3, 11],
'2005': [9, 7, np.nan],
'2010': [19, 19, np.nan],
'2015': [11, 9, np.nan]
}
df = pd.DataFrame(data)
print("原始数据:")
print(df)输出:
Index Country 1990 1995 2000 2005 2010 2015 0 0 US 5.0 6.0 NaN 9.0 19.0 11.0 1 1 Germany 5.0 NaN 3.0 7.0 19.0 9.0 2 2 Japan 9.0 NaN 11.0 NaN NaN NaN
✅ 正确填充方法(推荐):
# 方法一:明确指定数值列起始位置(假设前2列为非数值列:'Index' 和 'Country')
# 注意:x[2:] 表示跳过前两个元素(即跳过 Index 和 Country 列)
df_filled = df.apply(
lambda x: x.fillna(x.iloc[2:].mean()),
axis=1
)
print("\n填充后数据(按行数值列均值):")
print(df_filled.round(1)) # 保留一位小数便于观察输出:
Index Country 1990 1995 2000 2005 2010 2015 0 0 US 5.0 6.0 9.0 9.0 19.0 11.0 1 1 Germany 5.0 8.2 3.0 7.0 19.0 9.0 2 2 Japan 9.0 10.0 11.0 10.0 10.0 10.0
? 关键说明:
- x.iloc[2:] 安全选取每行从第3列(索引2)开始的所有值,自动排除 'Index' 和 'Country';
- x.fillna(...) 在当前行内原地填充,仅影响该行的 NaN;
- axis=1 确保函数按行应用,每行独立计算其数值子集的均值。
⚠️ 注意事项与进阶建议:
-
列定位更稳健的方式:若列顺序可能变化,建议显式指定数值列名,例如:
numeric_cols = ['1990', '1995', '2000', '2005', '2010', '2015'] df_filled = df.apply(lambda x: x.fillna(x[numeric_cols].mean()), axis=1)
-
类型一致性:填充后,原整数列可能转为 float64(因 NaN 强制类型提升)。如需恢复整数类型(且确认无小数),可用:
df_filled[numeric_cols] = df_filled[numeric_cols].apply(pd.to_numeric, downcast='integer')
- 性能提示:对超大表(>10万行),apply(axis=1) 效率较低;此时可考虑 numpy 向量化操作或分块处理。
总结而言,df.apply(lambda x: x.fillna(x[numeric_slice].mean()), axis=1) 是处理“首列为标识符+后续数值列含 NaN”场景最清晰、可控且易于理解的标准解法。它既保持了原始结构完整性,又实现了精准的行级统计填充。










