You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Polars中用自定义函数填充指定列空值(替代Pandas实现)

问题

我有一段Pandas代码:

df[col] = (
            df[col]
            .fillna(method="ffill", limit=1)
            .apply(lambda x: my_function(x))
        )

想要改写成Polars代码,尝试了以下实现:

df = df.with_columns(
            pl.col(col)
            .fill_null(strategy="forward", limit=1)
            .map_elements(lambda x: my_function(x))
        )

但代码未正常工作:向前填充策略生效,但自定义函数未处理剩余缺失值。

测试代码

import polars as pl
import pandas as pd
import numpy as np

df_polars = pl.DataFrame(
    {"A": [1, 2, None, None, None, None, 4, None], "B": [5, None, None, None, None, 7, None, 9]}
)

df_pandas = pd.DataFrame(
    {"A": [1, 2, None, None, None, None, 4, None], "B": [5, None, None, None, None, 7, None, 9]}
)

last_valid_data: int


def my_function(x):
    global last_valid_data
    if x == None or np.isnan(x):
        result = last_valid_data * 10
    else:
        last_valid_data = x
        result = x
    return result


col = "A"

last_valid_data = df_pandas[col][0]
df_pandas[col] = df_pandas[col].fillna(method="ffill", limit=1).apply(lambda x: my_function(x))

last_valid_data = df_polars[col][0]
df_polars = df_polars.with_columns(
    pl.col(col).fill_null(strategy="forward", limit=1).map_elements(lambda x: my_function(x))
)

Pandas期望输出

A    B
0   1.0  5.0
1   2.0  NaN
2   2.0  NaN
3  20.0  NaN
4  20.0  NaN
5  20.0  7.0
6   4.0  NaN
7   4.0  9.0

Polars当前输出

┌──────┬──────┐
│ A    ┆ B    │
│ ---  ┆ ---  │
│ i64  ┆ i64  │
╞══════╪══════╡
│ 1    ┆ 5    │
│ 2    ┆ null │
│ 2    ┆ null │
│ null ┆ null │
│ null ┆ null │
│ null ┆ 7    │
│ 4    ┆ null │
│ 4    ┆ 9    │
└──────┴──────┘
解决方案

问题根源

Polars的map_elements默认参数skip_nulls=True,会自动跳过null值,不会把这些缺失值传入my_function处理,所以剩余的null值没被替换成预期的last_valid_data *10。

修改后的代码

给map_elements加上skip_nulls=False参数,强制所有值(包括null)都进入自定义函数处理:

last_valid_data = df_polars[col][0]
df_polars = df_polars.with_columns(
    pl.col(col)
    .fill_null(strategy="forward", limit=1)
    .map_elements(lambda x: my_function(x), skip_nulls=False)
)

验证结果

修改后运行代码,Polars输出会和Pandas的期望输出一致:

┌──────┬──────┐
│ A    ┆ B    │
│ ---  ┆ ---  │
│ i64  ┆ i64  │
╞══════╪══════╡
│ 1    ┆ 5    │
│ 2    ┆ null │
│ 2    ┆ null │
│ 20   ┆ null │
│ 20   ┆ null │
│ 20   ┆ 7    │
│ 4    ┆ null │
│ 4    ┆ 9    │
└──────┴──────┘

更优实现(避免全局变量)

使用全局变量存在并行处理时的安全隐患,推荐用Polars原生的窗口状态函数替代,更符合向量化处理逻辑:

def polars_style_process(col_name):
    return (
        pl.col(col_name)
        .fill_null(strategy="forward", limit=1)
        .scan(lambda s: s.running_map(lambda acc, x: x if x is not None else acc * 10, initial=s.first()))
    )

df_polars = df_polars.with_columns(polars_style_process(col))

内容的提问来源于stack exchange,提问作者Honio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 09:23:11