基于索引用上方值填充NaN及按ID填充Pandas DataFrame NaN的方法
我来帮你搞定这两个Pandas里的NaN填充问题,都是日常数据清洗中非常常见的需求:
问题1:用上方前一个有效值填充NaN
在Pandas里,实现这个需求最直接的方式就是用fillna()方法,指定method='ffill'(全称forward fill,向前填充)。这个方法会沿着索引方向,把每个NaN替换成它上方(前一行)的第一个有效值。
举个简单的示例代码:
import pandas as pd import numpy as np # 构造测试数据 df = pd.DataFrame({'数值列': [10, np.nan, 30, np.nan, np.nan, 60]}) # 执行向前填充 df['填充后列'] = df['数值列'].fillna(method='ffill') print(df)
运行后输出结果:
数值列 填充后列 0 10.0 10.0 1 NaN 10.0 2 30.0 30.0 3 NaN 30.0 4 NaN 30.0 5 60.0 60.0
补充几个实用细节:
- 如果想对整个DataFrame的所有列都执行这个操作,直接用
df.fillna(method='ffill')即可 - 如果数据开头就有NaN,
ffill不会填充它(因为前面没有有效值),如果需要处理这种情况,可以结合向后填充bfill,比如df.fillna(method='ffill').fillna(method='bfill') - 可以用
limit参数限制连续填充的NaN数量,比如df['数值列'].fillna(method='ffill', limit=2)只会填充最多2个连续的NaN
问题2:按ID分组,用对应ID的有效值填充NaN
这个场景需要先按ID分组,再在每个组内完成填充。针对你给出的示例(每个ID只有一个有效值),这里有几种简单且实用的实现方式:
方法1:分组后用向前填充
因为每个ID的第一个值就是有效值,后面全是NaN,分组后用ffill就能快速覆盖所有同组的NaN:
import pandas as pd import numpy as np # 你的示例数据 df = pd.DataFrame({ 'ID': [1,1,1,1,1,2,2,2,2,3,3,3], 'COL': [23, np.nan, np.nan, np.nan, np.nan, 21, np.nan, np.nan, np.nan,25,np.nan,np.nan] }) # 分组执行向前填充 df['COL'] = df.groupby('ID')['COL'].ffill() print(df)
方法2:用transform取组内有效值填充(更健壮)
如果你的实际数据中,有些ID的有效值不是在第一行(比如中间行有有效值),可以用transform获取组内的第一个非NaN值,来填充整个组的NaN:
df['COL'] = df.groupby('ID')['COL'].transform(lambda x: x.fillna(x.dropna().iloc[0]))
这个方法不管有效值在组内的哪个位置,只要组内有至少一个有效值,就能完成填充。
方法3:先提取ID对应有效值再合并填充
如果你需要单独保存每个ID对应的有效值,也可以先提取出这部分数据,再合并回原DataFrame填充:
# 提取每个ID的第一个有效值 id_valid_values = df.groupby('ID')['COL'].first().reset_index() # 合并回原数据并填充NaN df = df.merge(id_valid_values, on='ID', suffixes=('', '_有效值')) df['COL'] = df['COL'].fillna(df['COL_有效值']) # 移除临时列 df.drop('COL_有效值', axis=1, inplace=True)
以上几种方法都能得到你预期的结果:所有同ID的COL列NaN都会被填充为该ID对应的有效值。
内容的提问来源于stack exchange,提问作者john doe
相关产品推荐
相关产品推荐

