如何用一行代码对DataFrame按列向前填充至各列最后有效索引
一行代码实现Pandas DataFrame的限定前向填充
问题说明
现有如下Pandas DataFrame:
import pandas as pd import numpy as np df = pd.DataFrame({ 'col1': [100, np.nan, np.nan, 100, np.nan, np.nan], 'col2': [np.nan, 100, np.nan, np.nan, 100, np.nan] })
输出结果:
col1 col2 0 100.0 NaN 1 NaN 100.0 2 NaN NaN 3 100.0 NaN 4 NaN 100.0 5 NaN NaN
需要将其转换为目标格式:
col1 col2 0 100.0 NaN 1 100.0 100.0 2 100.0 100.0 3 100.0 100.0 4 NaN 100.0 5 NaN NaN
当前实现是逐列应用自定义方法:
def ffill_last_valid(s): last_valid = s.last_valid_index() s = s.ffill() s[s.index > last_valid] = np.nan return s df.apply(ffill_last_valid)
以下提供两种一行代码的简洁实现方式:
实现方式一:基于布尔矩阵过滤
df.ffill().where(df.notna().cummax().iloc[::-1].cummax().iloc[::-1])
原理拆解
df.ffill():先对整个DataFrame执行前向填充,得到所有NaN被前置有效值填充后的临时结果。df.notna().cummax():生成布尔矩阵,标记从第0行到当前行是否出现过有效值(一旦出现有效值,后续行均为True)。.iloc[::-1].cummax().iloc[::-1]:将布尔矩阵反转后做累积最大值,再反转回来,得到的矩阵会标记当前行到最后一行是否存在有效值——只有该区间内有有效值的位置,才保留前向填充结果。.where():用上述布尔矩阵过滤前向填充结果,不符合条件的位置重置为NaN,完全匹配需求。
实现方式二:基于列最后有效索引判断
df.ffill().mask(df.apply(lambda s: s.index > s.last_valid_index()))
原理拆解
df.apply(lambda s: s.index > s.last_valid_index()):逐列生成布尔序列,标记哪些行的索引超过了该列最后一个有效值的索引。.mask():将这些标记为True的位置(即超过最后有效值的行)重新设为NaN,逻辑和自定义函数完全一致,但写法更紧凑。
内容的提问来源于stack exchange,提问作者data-monkey
相关产品推荐
相关产品推荐

