Pandas实现按条件填充指定行缺失值(非固定行偏移)
解决Pandas DataFrame的定向填充需求
先看你的示例DataFrame:
import pandas as pd import numpy as np df = pd.DataFrame( {"col1": ["A", "B", "C", "D", "E", "A", "E", "B", "D"], "col2": [1, np.NAN, 3, 4, np.NAN, 6, np.NAN, np.NAN, 8], })
对应的初始数据:
| id | col1 | col2 |
|---|---|---|
| 0 | A | 1.0 |
| 1 | B | NaN |
| 2 | C | 3.0 |
| 3 | D | 4.0 |
| 4 | E | NaN |
| 5 | A | 6.0 |
| 6 | E | NaN |
| 7 | B | NaN |
| 8 | D | 8.0 |
你的需求很明确:
- 对于
col1为"E"且col2为空的行,用之前最近的col1为"A"的行的col2值填充 - 对于
col1为"B"且col2为空的行,用之后最近的col1为"D"的行的col2值填充
下面是简洁的实现脚本,完全不用大量if-else,利用Pandas的分组和填充特性来搞定:
import pandas as pd import numpy as np # 初始化DataFrame df = pd.DataFrame( {"col1": ["A", "B", "C", "D", "E", "A", "E", "B", "D"], "col2": [1, np.NAN, 3, 4, np.NAN, 6, np.NAN, np.NAN, 8], }) # 处理需求1:填充E的NaN为最近的前面的A的col2值 # 先标记A的位置,向前填充(ffill)所有位置,然后只更新E的NaN行 a_values = df['col2'].where(df['col1'] == 'A').ffill() df.loc[(df['col1'] == 'E') & df['col2'].isna(), 'col2'] = a_values[(df['col1'] == 'E') & df['col2'].isna()] # 处理需求2:填充B的NaN为最近的后面的D的col2值 # 标记D的位置,向后填充(bfill)所有位置,然后只更新B的NaN行 d_values = df['col2'].where(df['col1'] == 'D').bfill() df.loc[(df['col1'] == 'B') & df['col2'].isna(), 'col2'] = d_values[(df['col1'] == 'B') & df['col2'].isna()] # 输出结果(转成int让结果更整洁) df['col2'] = df['col2'].astype(int) print(df)
执行后得到的结果正好符合你的期望:
| id | col1 | col2 |
|---|---|---|
| 0 | A | 1 |
| 1 | B | 4 |
| 2 | C | 3 |
| 3 | D | 4 |
| 4 | E | 1 |
| 5 | A | 6 |
| 6 | E | 6 |
| 7 | B | 8 |
| 8 | D | 8 |
代码解释
- 对于需求1:用
where筛选出A行的col2值,其他位置为NaN,然后用ffill()向前填充,这样每个位置都能拿到最近的前面的A的值,最后只把E的NaN行替换成这个值。 - 对于需求2:类似地,用
where筛选D行的col2值,bfill()向后填充,拿到每个位置最近的后面的D的值,再替换B的NaN行。
这种方法完全利用Pandas的矢量化操作,比循环或大量if-else高效得多,代码也简洁易读。
内容的提问来源于stack exchange,提问作者cincin21
相关产品推荐
相关产品推荐

