讲师中心 微信公众号
AI工具推荐 视频效率加速

Polars UDF 行级映射与多行结果 DataFrame 的高效拼接

冬萱姑娘_6646

冬萱姑娘_6646

发布时间:2026-02-22 10:23:00

|

479人浏览过

|

来源于php中文网

原创

Polars UDF 行级映射与多行结果 DataFrame 的高效拼接

本文详解如何在 Polars 中正确实现「每行输入生成一个同结构但行数可变的 DataFrame」的 UDF 模式,对比 map_rows、iter_rows + concat 与表达式向量化三种方案,强调性能陷阱与最佳实践。

本文详解如何在 polars 中正确实现「每行输入生成一个同结构但行数可变的 dataframe」的 udf 模式,对比 `map_rows`、`iter_rows + concat` 与表达式向量化三种方案,强调性能陷阱与最佳实践。

在 Polars 中,当需要对每一行输入执行复杂逻辑(如基于参数切片参考数据、生成变长结果集)并最终合并为单个 DataFrame 时,开发者常误用 map_rows 返回嵌套 DataFrame,导致性能劣化与类型混乱。核心原则是:map_rows 本质是逐行标量映射,不适用于返回多行结构;真正支持“1→N”行扩展的操作应使用 iter_rows + pl.concat() 或(更优)完全向量化表达式重构。

✅ 推荐方案一:避免 map_rows,改用 iter_rows + pl.concat()

这是最直接、语义清晰且可控性高的方式,尤其适合逻辑无法轻易向量化(如需调用外部库、动态切片大表等)的场景:

import polars as pl

df = pl.DataFrame({
    "foo": [1, 2, 3],
    "bar": [6.0, 7.0, 8.0],
    "ham": ["a", "b", "c"],
})

reference_data = pl.DataFrame({
    "x": list(range(10)),
    "y": [chr(ord("a") + i % 26) for i in range(10)],
})

def myUDF(row_tuple):
    foo, bar, ham = row_tuple
    # 动态切片:从 foo 开始取 floor(bar/2) 行
    n_rows = int(bar / 2)
    return (
        reference_data
        .slice(foo, n_rows)
        .with_columns(name=pl.lit(ham))
    )

# ✅ 正确做法:逐行调用 UDF 并拼接
result = pl.concat([myUDF(row) for row in df.iter_rows()], how="vertical")
print(result)

输出:

shape: (10, 3)
┌─────┬─────┬──────┐
│ x   ┆ y   ┆ name │
│ --- ┆ --- ┆ ---  │
│ i64 ┆ str ┆ str  │
╞═════╪═════╪══════╡
│ 1   ┆ b   ┆ a    │
│ 2   ┆ c   ┆ a    │
│ 3   ┆ d   ┆ a    │
│ 2   ┆ c   ┆ b    │
│ 3   ┆ d   ┆ b    │
│ 4   ┆ e   ┆ b    │
│ 3   ┆ d   ┆ c    │
│ 4   ┆ e   ┆ c    │
│ 5   ┆ f   ┆ c    │
│ 6   ┆ g   ┆ c    │
└─────┴─────┴──────┘

⚠️ 注意事项:

  • pl.concat(..., how="vertical") 要求所有子 DataFrame 具有完全一致的 schema(列名、类型、顺序),否则会报错;
  • iter_rows() 返回 Python tuple,默认按列顺序解包,确保 UDF 内部解构顺序与 DataFrame 列序严格一致;
  • 若 reference_data 极大(如千万级),建议预先 .lazy() 化并在 UDF 中构建 LazyFrame,最后统一 .collect(),避免重复 eager 计算。

✅ 推荐方案二:彻底向量化 —— 用 Polars 表达式替代 UDF(最高性能)

若逻辑可表达为列运算(如本例中“切片范围由 foo 和 bar 决定”),应优先放弃行级循环,转为纯表达式操作:

# ✅ 向量化实现(无 Python 循环,充分利用 Polars 引擎)
result_vec = (
    df
    .with_row_index("row_idx")  # 添加索引用于后续 join 或 expand
    .with_columns(
        start = pl.col("foo"),
        stop = (pl.col("bar") / 2).cast(pl.Int64),
        name = pl.col("ham")
    )
    # 生成每个 row 对应的 range(start, stop),再 explode 展开
    .with_columns(
        range_list = pl.arange(pl.col("start"), pl.col("stop"), eager=False)
    )
    .explode("range_list")
    .join(
        reference_data.rename({"x": "range_list"}),
        on="range_list",
        how="left"
    )
    .select("x", "y", "name")
)

该方式零 Python 解释器开销,支持多线程并行,是 Polars 的设计哲学首选。

❌ 不推荐方案:滥用 map_rows 返回 DataFrame

map_rows 的设计目标是返回标量元组(如 (a, b)),其输出会被自动构造成新 DataFrame 的一行。若在函数内创建 DataFrame 并返回(如 return (result,)),Polars 仅将其作为 object 类型存储,后续需 .unnest().explode() 等昂贵操作,丧失 Polars 的内存与计算优势:

# ❌ 反模式:低效、类型丢失、难以调试
df.map_rows(lambda r: (pl.DataFrame({"a": [r[0]+r[1]], "b": [r[2]]}),))

总结:选择路径的决策树

场景 推荐方式 理由
逻辑完全可用 Polars 表达式描述(如算术、条件、窗口、join) 纯表达式链 最高性能、可并行、惰性优化、类型安全
需动态访问外部资源 / 调用非 Polars 函数 / 复杂控制流 iter_rows() + pl.concat() 语义明确、易于调试、可控性强;注意 schema 一致性
临时调试或极小数据集 map_rows + 标量元组(非 DataFrame) 仅限简单 1→1 映射,避免嵌套结构

记住:Polars 的强大源于列式计算与查询优化器,而非模拟 Pandas 的 .apply(axis=1)。拥抱向量化,谨慎使用行级迭代——这才是“正确的 Polars 方式”。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

相关专题

更多
Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

320

2025.12.04

Python 数据清洗与预处理实战
Python 数据清洗与预处理实战

本专题系统讲解 Python 在数据清洗与预处理中的核心技术,包括使用 Pandas 进行缺失值处理、异常值检测、数据格式化、特征工程与数据转换,结合 NumPy 高效处理大规模数据。通过实战案例,帮助学习者掌握 如何处理混乱、不完整数据,为后续数据分析与机器学习模型训练打下坚实基础。

252

2026.01.31

Python数据分析与Pandas高级实战
Python数据分析与Pandas高级实战

本专题围绕 Python 数据分析展开,系统讲解 Pandas 的高级用法,包括数据清洗、透视表、时间序列分析以及多表合并与分组操作。通过实战案例,帮助开发者掌握高效处理与分析数据的方法,提高数据处理效率与分析能力。

591

2026.04.13

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4258

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

1189

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

403

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

559

2026.01.21

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

389

2026.02.06

剧云故事大纲与分场规划教程
剧云故事大纲与分场规划教程

本专题讲解剧云梗概与多级大纲功能,覆盖全局、分集、分场结构生成,以及主线冲突、剧情节点和场次顺序调整。

0

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn