0

0

如何使用Polars高效加载多文件并添加自定义源信息

花韻仙語

花韻仙語

发布时间:2025-09-27 10:52:23

|

594人浏览过

|

来源于php中文网

原创

如何使用polars高效加载多文件并添加自定义源信息

本教程旨在详细阐述如何利用Polars的惰性计算(LazyFrames)功能,高效地加载多个结构相似的CSV文件,并在合并数据时为每条记录添加其来源文件的信息(例如,从文件名提取产品代码)。文章将通过示例代码演示如何结合scan_csv、with_columns和concat,实现高性能且灵活的多文件数据处理策略。

1. 引言:多文件数据合并与挑战

在数据分析和处理中,我们经常会遇到需要处理大量结构相同但分散在多个文件中的数据。例如,一系列按产品或日期划分的CSV文件:data_product_1.csv、data_product_2.csv等。Polars作为一款高性能的数据框库,提供了便捷的方式来合并这些文件,例如使用通配符直接读取:pl.read_csv("data_*.csv")。

然而,一个常见的需求是在合并后的数据中保留每条记录的原始文件信息。例如,将文件名中的“product_1”提取出来作为新的“product_code”列。虽然可以通过逐个文件加载、添加列、然后合并的传统方法实现,但这可能无法充分利用Polars在处理大量数据时的性能优势,尤其是在面对大数据集时。本教程将深入探讨如何利用Polars的惰性计算特性,以一种高效且并行的方式解决这一问题。

2. 传统方法与Polars的惰性优势

对于多文件处理并添加源信息的需求,一种直观但可能效率不高的方法是:

  1. 遍历所有目标文件。
  2. 对每个文件,使用 pl.read_csv() 加载数据。
  3. 在加载后的DataFrame中添加一列,包含该文件的标识信息(例如文件名)。
  4. 将所有处理过的DataFrame收集到一个列表中。
  5. 最后使用 pl.concat() 将它们合并。

这种方法在文件数量不多或文件较小时尚可接受,但当文件数量庞大或单个文件体积较大时,会因为频繁的I/O操作和内存占用而导致性能瓶颈。此外,某些数据库系统(如DuckDB)提供了在读取CSV时直接添加文件名列的功能(例如 read_csv_auto('data_*.csv', filename = true)),这显示了此类功能的实用性。

Polars虽然在 read_csv 或 scan_csv 中尚未直接内置 filename=true 这样的参数(截至本文撰写时,此功能仍在社区讨论中),但其强大的惰性计算(LazyFrames)机制为我们提供了一个优雅且高性能的解决方案。通过利用惰性操作,Polars可以构建一个执行计划,在实际执行前进行优化,并能以并行方式处理多个文件,从而显著提升效率。

3. 利用Polars LazyFrames高效处理多文件

Polars的惰性API是解决此问题的核心。它允许我们定义一系列数据转换操作,而无需立即加载或计算数据。只有当明确调用 .collect() 方法时,Polars才会执行这些操作并返回一个具体的DataFrame。

AOXO_CMS建站系统企业通用版1.0
AOXO_CMS建站系统企业通用版1.0

一个功能强大、性能卓越的企业建站系统。使用静态网页技术大大减轻了服务器负担、加快网页的显示速度、提高搜索引擎推广效果。本系统的特点自定义模块多样化、速度快、占用服务器资源小、扩展性强,能方便快捷地建立您的企业展示平台。简便高效的管理操作从用户使用的角度考虑,对功能的操作方便性进行了设计改造。使用户管理的工作量减小。网站互动数据可导出Word文档,邮件同步发送功能可将互动信息推送到指定邮箱,加快企业

下载

3.1 惰性扫描文件 (scan_csv)

与 pl.read_csv() 直接加载数据不同,pl.scan_csv() 返回一个 LazyFrame 对象。LazyFrame 只是一个操作计划的表示,它不会立即读取文件内容,从而节省了内存和计算资源。

import polars as pl
from pathlib import Path

# 假设当前目录下有 data_product_1.csv, data_product_2.csv 等文件
# 为了演示,我们先创建一些模拟文件
file_contents = """data,value
2000-01-01,1
2000-01-02,2
"""
Path("data_product_1.csv").write_text(file_contents)

file_contents_2 = """data,value
2000-01-01,3
2000-01-02,4
"""
Path("data_product_2.csv").write_text(file_contents_2)

file_contents_3 = """data,value
2000-01-01,4
2000-01-02,5
"""
Path("data_product_3.csv").write_text(file_contents_3)

# 遍历所有匹配的文件,并为每个文件创建一个LazyFrame
csv_lazyframes = []
for f_path in Path().glob("data_*.csv"):
    # 使用 scan_csv 惰性读取文件
    lazy_df = pl.scan_csv(f_path)
    csv_lazyframes.append(lazy_df)

# 此时,数据尚未被实际读取
print(f"创建了 {len(csv_lazyframes)} 个 LazyFrame 对象。")

3.2 添加源信息列 (with_columns)

在创建 LazyFrame 后,我们可以立即在其上链式调用各种转换操作,例如添加新列。这里,我们将利用 f_path.name 获取文件名,并将其作为新的 product_code 列添加到每个 LazyFrame 中。pl.lit() 用于将Python字符串转换为Polars字面量表达式。

import polars as pl
from pathlib import Path

# (省略模拟文件创建部分,假设文件已存在)

# 遍历所有匹配的文件,并为每个文件创建一个LazyFrame,同时添加product_code列
csv_lazyframes_with_product_code = [
    pl.scan_csv(f_path).with_columns(product_code=pl.lit(f_path.name))
    for f_path in Path().glob("data_*.csv")
]

# 此时,每个LazyFrame都包含一个添加product_code列的指令,但数据仍未加载
print(f"创建了 {len(csv_lazyframes_with_product_code)} 个包含 'product_code' 列指令的 LazyFrame 对象。")

3.3 并行合并 (concat) 与数据收集 (collect)

Polars的 pl.concat() 函数不仅可以合并Eager DataFrame,也能高效地合并 LazyFrame 列表。当合并 LazyFrame 时,pl.concat() 默认会利用多核CPU并行处理各个文件的读取和转换操作,从而大大加快处理速度。最后,调用 .collect() 方法会触发所有惰性操作的实际执行,将结果物化为一个最终的Polars DataFrame。

import polars as pl
from pathlib import Path

# 1. 创建模拟数据文件 (如果尚未创建)
file_contents_1 = """data,value
2000-01-01,1
2000-01-02,2
"""
Path("data_product_1.csv").write_text(file_contents_1)

file_contents_2 = """data,value
2000-01-01,3
2000-01-02,4
"""
Path("data_product_2.csv").write_text(file_contents_2)

file_contents_3 = """data,value
2000-01-01,4
2000-01-02,5
"""
Path("data_product_3.csv").write_text(file_contents_3)


# 2. 核心解决方案:使用LazyFrames处理和合并文件
# 遍历文件,创建LazyFrame,并添加文件名作为product_code列
lazy_frames = [
    pl.scan_csv(f_path).with_columns(product_code=pl.lit(f_path.name))
    for f_path in Path().glob("data_*.csv")
]

# 使用pl.concat合并所有LazyFrames,并调用.collect()执行计算
# pl.concat在处理LazyFrames时会默认尝试并行化读取和转换操作
final_df = pl.concat(lazy_frames).collect()

# 3. 打印结果
print("最终合并的DataFrame:")
print(final_df)

# 清理模拟文件
Path("data_product_1.csv").unlink()
Path("data_product_2.csv").unlink()
Path("data_product_3.csv").unlink()

输出示例:

最终合并的DataFrame:
shape: (6, 3)
┌────────────┬───────┬────────────────────┐
│ data       ┆ value ┆ product_code       │
│ ---        ┆ ---   ┆ ---                │
│ str        ┆ i64   ┆ str                │
╞════════════╪═══════╪════════════════════╡
│ 2000-01-01 ┆ 1     ┆ data_product_1.csv │
│ 2000-01-02 ┆ 2     ┆ data_product_1.csv │
│ 2000-01-01 ┆ 3     ┆ data_product_2.csv │
│ 2000-01-02 ┆ 4     ┆ data_product_2.csv │
│ 2000-01-01 ┆ 4     ┆ data_product_3.csv │
│ 2000-01-02 ┆ 5     ┆ data_product_3.csv │
└────────────┴───────┴────────────────────┘

4. 核心优势与注意事项

  • 惰性计算与性能优化: 这种方法的核心优势在于惰性计算。Polars可以构建一个全局的执行计划,并对所有操作进行优化,避免不必要的中间数据加载和存储。对于大量文件或大型文件,这能显著减少内存占用和提高处理速度。
  • 并行处理: pl.concat 在处理 LazyFrame 列表时,会默认利用多核CPU并行读取和处理各个文件,进一步加速数据整合过程。
  • 灵活性: 在 with_columns 步骤中,你可以执行更复杂的逻辑来从文件名中提取信息。例如,如果文件名是 data_product_1.csv,你可以使用字符串操作 pl.col("product_code").str.extract(r"product_(\d+)") 来提取纯粹的产品编号。
  • 文件命名规范: 从文件名提取信息的前提是文件命名具有一致性和可解析性。清晰的命名约定将使信息提取变得简单可靠。
  • Polars的演进: 尽管目前需要手动添加文件名列,但Polars社区正在积极开发新功能。未来版本中可能会直接在 read_csv 或 scan_csv 中提供类似 filename=true 的参数,届时处理方式可能会更加简化。

5. 总结

通过本教程,我们学习了如何利用Polars的 scan_csv、with_columns 和 concat 结合 LazyFrame 的特性,高效地处理多个CSV文件,并在合并过程中为每条记录添加源文件信息。这种方法不仅解决了特定场景下的数据处理需求,更展示了Polars在处理大数据集时卓越的性能和灵活性。掌握Polars的惰性API是提升数据处理效率的关键,尤其适用于需要复杂转换和大规模数据整合的场景。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

319

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1502

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

624

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

653

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

609

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

172

2025.07.29

c++字符串相关教程
c++字符串相关教程

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

83

2025.08.07

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

8

2026.01.30

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 3.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号