如何在Polars中实现横向向前填充(horizontal forward_fill)
在Polars中实现按列向前填充(等价于pandas的
.ffill(axis=1)) 需要在Polars中实现行方向的向前填充,效果等价于pandas中的.ffill(axis=1),即对每一行的列从左到右,用左侧最近的非空值填充当前的null值。
示例数据
df = pl.DataFrame( { "id": ["NY", "TK", "FD"], "eat2000": [1, 6, 3], "eat2001": [-2, None, 4], "eat2002": [None, None, None], "eat2003": [-9, 3, 8], "eat2004": [None, None, 8] } ); df
数据输出:
shape: (3, 6) ┌─────┬─────────┬─────────┬─────────┬─────────┬─────────┐ │ id ┆ eat2000 ┆ eat2001 ┆ eat2002 ┆ eat2003 ┆ eat2004 │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ i64 ┆ i64 ┆ f64 ┆ i64 ┆ i64 │ ╞═════╪═════════╪═════════╪═════════╪═════════╪═════════╡ │ NY ┆ 1 ┆ -2 ┆ null ┆ -9 ┆ null │ │ TK ┆ 6 ┆ null ┆ null ┆ 3 ┆ null │ │ FD ┆ 3 ┆ 4 ┆ null ┆ 8 ┆ 8 │ └─────┴─────────┴─────────┴─────────┴─────────┴─────────┘
当前实现方式(转Pandas)
pl.from_pandas(df.to_pandas().ffill(axis=1))
效果输出:
shape: (3, 6) ┌─────┬─────────┬─────────┬─────────┬─────────┬─────────┐ │ id ┆ eat2000 ┆ eat2001 ┆ eat2002 ┆ eat2003 ┆ eat2004 │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ i64 ┆ f64 ┆ f64 ┆ i64 ┆ f64 │ ╞═════╪═════════╪═════════╪═════════╪═════════╪═════════╡ │ NY ┆ 1 ┆ -2.0 ┆ -2.0 ┆ -9 ┆ -9.0 │ │ TK ┆ 6 ┆ 6.0 ┆ 6.0 ┆ 3 ┆ 3.0 │ │ FD ┆ 3 ┆ 4.0 ┆ 4.0 ┆ 8 ┆ 8.0 │ └─────┴─────────┴─────────┴─────────┴─────────┴─────────┘
Polars原生实现方式
方法一:列表转换+向前填充+结构体展开
通过将行内列转换为列表,执行向前填充后再拆回原列结构:
# 指定需要填充的列(排除id列) fill_columns = df.columns[1:] df_ffill = df.with_columns( pl.concat_list(fill_columns) .list.forward_fill() # 对列表内元素执行行方向向前填充 .list.to_struct(fields=fill_columns) # 将填充后的列表转回结构体 .alias("filled_cols") ).unnest("filled_cols") # 展开结构体为原列 print(df_ffill)
方法二:pl.fold逐列累积非空值
使用pl.fold函数逐列累积每一行的最近非空值,实现行方向填充:
fill_columns = df.columns[1:] df_ffill = df.with_columns( pl.fold( acc=None, func=lambda acc, col: pl.coalesce(col, acc), # 优先取当前列值,否则用累积的非空值 exprs=fill_columns ).alias(col) for col in fill_columns ) print(df_ffill)
两种方法均能得到与Pandas.ffill(axis=1)完全一致的结果,且保留Polars的原生性能优势。
内容的提问来源于stack exchange,提问作者codedancer
相关产品推荐
相关产品推荐

