Article

数据计算 Polars

更新于:2026-07-13

第1章:Polars 简介与环境搭建

1.1 什么是 Polars?与 Pandas 的对比

概念说明注意事项
Polars 简介Polars 是一个基于 Apache Arrow 内存格式的高性能 DataFrame 库,使用 Rust 编写,支持多线程并行计算,提供 Python 和 Node.js 接口。其核心优势是速度快、内存效率高。Polars 专为现代 CPU 架构优化,适合处理大规模数据集(百万至十亿级行)。
与 Pandas 对比• 性能:Polars 使用向量化执行引擎和多线程,远快于 Pandas(尤其在聚合、过滤等操作)。
• 内存效率:基于 Arrow,零拷贝共享内存。
• API 设计:Polars 推崇表达式(Expression)编程,更函数式;Pandas 更命令式。
• 缺失值处理:Polars 明确区分 null 与 NaN,类型更安全。
• 惰性求值:Polars 支持 LazyFrame,可优化执行计划;Pandas 为立即执行。
• 学习曲线略陡,需适应表达式风格。
• 某些 Pandas 小众功能尚未完全覆盖。
• 生态仍在发展中,第三方集成较少。

1.2 安装 Polars 与依赖环境配置

方法语法用途代码示例注意事项
pip install polarspip install polars安装核心 Polars 库pip install polars推荐使用虚拟环境(如 venv 或 conda)避免依赖冲突。
pip install ‘polars[all]‘pip install 'polars[all]'安装带可选依赖的 Polars(如 parquet、xlsx)pip install 'polars[parquet,xlsx]'使用 [all] 安装所有可选功能,适合数据分析环境。
验证安装import polars as pl检查是否成功导入import polars as pl
print(pl.__version__)
若报错,检查 Python 版本(需 3.8+)和 pip 是否为最新。

1.3 启用 Polars 的可选功能(如 lazy evaluation、parallel execution)

概念说明注意事项
惰性求值(Lazy Evaluation)使用 pl.LazyFrame 可延迟执行,构建执行计划后通过 collect() 触发。Polars 自动优化查询(如谓词下推、列投影)。适合复杂管道,避免中间结果占用内存。
并行执行Polars 默认启用多线程并行(如 group_by、join),线程数由环境变量 POLARS_MAX_THREADS 控制。无需手动配置,自动利用 CPU 多核。
启用 Arrow 扩展类型可通过 pl.Config 启用对 Arrow 类型的兼容显示。一般无需手动设置,内部已优化。
配置日志与调试使用 pl.Config.set_fmt_str_lengths() 等调整输出格式。用于调试长字符串截断等问题。

第2章:基础数据结构:Series 与 DataFrame

2.1 Series 的创建与基本操作

方法语法用途代码示例注意事项
pl.Series()pl.Series(name, values, dtype)创建 Seriess = pl.Series("age", [25, 30, 35])name 可省略,values 支持 list、numpy array 等。
.dtypeseries.dtype查看数据类型s.dtype返回 Polars 类型(如 Int64、Utf8)。
.to_list()series.to_list()转为 Python 列表s.to_list()大数据集慎用,可能占用内存。
.head() / .tail()series.head(n) / series.tail(n)查看前/后 n 个元素s.head(2)默认 n=5。
.is_null()series.is_null()返回布尔 Series,标记缺失值s.is_null()用于缺失值检测。
.fill_null()series.fill_null(value)填充缺失值s.fill_null(0)支持多种策略(如 “forward”, “backward”)。

2.2 DataFrame 的创建方式(字典、列表、NumPy 数组等)

方法语法用途代码示例注意事项
字典创建pl.DataFrame({'col1': ..., 'col2': ...})从字典创建 DataFramedf = pl.DataFrame({
"name": ["Alice", "Bob"],
"age": [25, 30]
})
键为列名,值为列表或 Series。
列表创建pl.DataFrame([[val1, val2], [val3, val4]], schema=['a','b'])从嵌套列表创建pl.DataFrame([[1,2],[3,4]], schema=['x','y'])需指定 schema 定义列名。
NumPy 数组pl.DataFrame(np.array(...), columns=...)从 NumPy 数组创建import numpy as np
data = np.array([[1,2],[3,4]])
df = pl.DataFrame(data, columns=['a','b'])
数组应为 2D。
Series 列表pl.DataFrame([s1, s2])从 Series 列表创建s1 = pl.Series("a", [1,2])
s2 = pl.Series("b", [3,4])
df = pl.DataFrame([s1, s2])
Series 长度需一致。
空 DataFramepl.DataFrame()创建空 DataFramedf = pl.DataFrame()可后续添加列。

2.3 查看与理解数据结构(shape, dtypes, head/tail, describe)

方法语法用途代码示例注意事项
.shapedf.shape返回 (行数, 列数)rows, cols = df.shape类似 NumPy/Pandas。
.dtypesdf.dtypes返回每列的数据类型列表df.dtypes顺序与列一致。
.columnsdf.columns返回列名列表df.columns可用于列遍历。
.head(n)df.head(n)查看前 n 行df.head(3)默认 n=5。
.tail(n)df.tail(n)查看后 n 行df.tail(2)默认 n=5。
.describe()df.describe()生成统计摘要(计数、均值、标准差等)df.describe()仅对数值列有效。
.schemadf.schema返回字典:列名 → 数据类型df.schema.dtypes 更结构化。

第3章:数据读取与写入

3.1 读取 CSV 文件(read_csv)

方法语法用途代码示例注意事项
pl.read_csv()pl.read_csv(source, ...)从 CSV 文件或路径读取数据df = pl.read_csv("data.csv")source 可为文件路径、URL 或文件对象。
separatorsep=','指定分隔符pl.read_csv("data.tsv", sep='\t')默认逗号。
has_headerhas_header=True是否包含列名pl.read_csv("no_header.csv", has_header=False)若为 False,自动生成列名。
columnscolumns=[0,1]['a','b']仅读取指定列pl.read_csv("big.csv", columns=["name","age"])节省内存。
dtypesdtypes={'age': pl.Int32}指定列的数据类型pl.read_csv("data.csv", dtypes={"id": pl.Utf8})避免类型推断错误。
n_rowsn_rows=1000仅读取前 n 行pl.read_csv("large.csv", n_rows=500)用于快速采样。
use_pyarrowuse_pyarrow=True使用 PyArrow 后端(更快)pl.read_csv("data.csv", use_pyarrow=True)需安装 pyarrow。

3.2 读取 Parquet 文件(read_parquet)

方法语法用途代码示例注意事项
pl.read_parquet()pl.read_parquet(source, ...)读取 Parquet 格式文件df = pl.read_parquet("data.parquet")Parquet 是列式存储,读取快且压缩率高。
columnscolumns=['a','b']仅读取指定列pl.read_parquet("data.parquet", columns=["x"])列投影优化,极快。
filtersfilters=[("age", ">", 30)]谓词下推,过滤行pl.read_parquet("data.parquet", filters=[("active", "==", True)])减少内存使用。
use_pyarrowuse_pyarrow=False是否使用 PyArrow 后端pl.read_parquet("data.parquet", use_pyarrow=True)默认使用 Polars 原生引擎。

3.3 读取 JSON、Excel、SQLite 等格式

方法语法用途代码示例注意事项
pl.read_json()pl.read_json(source)读取 JSON 文件(通常为 list of dicts)df = pl.read_json("data.json")支持 line_delimited=True 读取 JSONL。
pl.read_excel()pl.read_excel(source, sheet_name="Sheet1")读取 Excel 文件(.xlsx)df = pl.read_excel("data.xlsx", sheet_name="Sales")需安装 openpyxl 或 xlsx2csv。
pl.read_database()pl.read_database(query, connection)从数据库读取(如 SQLite)import sqlite3
conn = sqlite3.connect("db.db")
df = pl.read_database("SELECT * FROM users", conn)
支持任何 DB-API 2.0 连接。
pl.read_ndjson()pl.read_ndjson(source)读取换行符分隔的 JSONdf = pl.read_ndjson("data.ndjson")适用于日志等流式数据。

3.4 写入数据到文件(write_csv, write_parquet 等)

方法语法用途代码示例注意事项
.write_csv()df.write_csv(file_path)写入 CSV 文件df.write_csv("output.csv")可指定 sep、header 等参数。
.write_parquet()df.write_parquet(file_path)写入 Parquet 文件df.write_parquet("output.parquet")支持压缩(compression="zstd")。
.write_json()df.write_json(file_path, orient="records")写入 JSON 文件df.write_json("output.json")orient 可为 “records”、“lines” 等。
.write_excel()df.write_excel(file_path)写入 Excel 文件df.write_excel("report.xlsx")需安装 xlsxwriter 或 openpyxl。
.write_database()df.write_database(table_name, connection)写入数据库表df.write_database("users", conn)自动创建表(若不存在)。
.write_ndjson()df.write_ndjson(file_path)写入换行符分隔的 JSONdf.write_ndjson("log.ndjson")适合流式写入。

第4章:数据查看与基本信息探索

4.1 查看前/后 N 行:head() 与 tail()

方法语法用途代码示例注意事项
.head(n)df.head(n)返回前 n 行df = pl.DataFrame({"a": [1,2,3,4,5], "b": ['x','y','z','w','v']})
df.head(3)
默认 n=5;若 n > row_count,返回全部数据。
.tail(n)df.tail(n)返回后 n 行df.tail(2)默认 n=5;常用于查看末尾记录。

4.2 数据摘要:describe() 与 schema 信息

方法语法用途代码示例注意事项
.describe()df.describe(percentiles=None)生成数值列的统计摘要df = pl.DataFrame({"age": [25,30,35,40], "score": [88,92,76,95]})
df.describe()
输出包括 count, mean, std, min, 25%, 50%, 75%, max;仅对数值类型列有效。
.schemadf.schema返回字典:列名 → Polars 数据类型df.schema类型为 pl.Int64, pl.Utf8 等,非字符串。
.glimpse()df.glimpse()快速查看结构(类似 info())df.glimpse()glimpse() 将列垂直显示,适合宽表。

4.3 列信息查看:columns, dtypes, shape

方法语法用途代码示例注意事项
.columnsdf.columns返回列名列表cols = df.columns可用于遍历或重命名。
.dtypesdf.dtypes返回每列的数据类型列表types = df.dtypes顺序与 .columns 一致。
.shapedf.shape返回元组 (行数, 列数)rows, cols = df.shape类似 NumPy 数组。
.height / .widthdf.height / df.width分别获取行数和列数n_rows = df.height更语义化,避免索引混淆。

第5章:数据选择与索引

5.1 列选择:单列、多列、列切片

方法语法用途代码示例注意事项
单列(属性)df.column_name通过属性访问单列(Series)df.age仅当列名是合法标识符时可用。
单列(键)df["column"]通过键访问列df["age"]通用方式,支持任意列名(含空格)。
多列选择df[["col1", "col2"]]返回新 DataFrame 包含指定列df[["name", "age"]]列顺序可调整。
列切片df[start:end]按列位置切片(不推荐)df[:2]实际是对行操作!列切片应使用 select()。
使用 select()df.select("col1", "col2")推荐的列选择方式df.select(pl.col("name"), pl.col("age"))支持表达式,功能强大。

5.2 行选择:使用索引与布尔索引

方法语法用途代码示例注意事项
布尔索引df[condition]根据条件筛选行df[df["age"] > 30]条件返回布尔 Series。
多条件(与)(cond1) & (cond2)组合多个条件df[(df["age"] > 25) & (df["score"] < 90)]必须加括号,使用 & 而非 and
多条件(或)(cond1) | (cond2)任一条件满足df[(df["city"] == "Beijing") | (df["city"] == "Shanghai")]使用 | 而非 or
索引选择行df[row_index]获取单行(返回 Series)df[0]返回第 0 行作为 Series。
行范围df[start:end]获取行切片df[1:4]类似 Python 切片,左闭右开。

5.3 使用 select()、with_columns()、filter() 进行列/行筛选

方法语法用途代码示例注意事项
select()df.select(exprs)选择列或表达式结果df.select(pl.col("name").str.to_uppercase())强大且高效,支持嵌套表达式。
with_columns()df.with_columns(new_cols)添加或替换列df.with_columns((pl.col("age") + 1).alias("age_next"))不修改原 DataFrame,返回新实例。
filter()df.filter(condition)筛选行(等价于布尔索引)df.filter(pl.col("score") >= 80)更函数式风格,支持复杂表达式。
组合使用链式调用构建数据处理管道df.filter(pl.col("age") > 20)
.select(["name", "score"])
.with_columns(pl.col("score").log().alias("log_score"))
推荐写法,清晰且惰性优化友好。

5.4 使用 row() 和 item() 提取标量值

方法语法用途代码示例注意事项
.item()expr.item()series.item()从单元素 Series 或表达式提取标量single = df.filter(pl.col("name") == "Alice").select("age").item()必须确保结果只有一个元素,否则报错。
.row(i)df.row(i)获取第 i 行为元组df.row(0)返回 Python 元组,不可变。
.rows()df.rows()获取所有行为元组列表df.rows()大数据集慎用,可能占用内存。
.item(row, col)df.item(row, col)通过行列索引提取单个值df.item(0, "age")col 可为列名或索引。

第6章:数据清洗与预处理

6.1 处理缺失值:is_null(), fill_null(), drop_nulls()

方法语法用途代码示例注意事项
.is_null()expr.is_null()返回布尔值标记缺失df.select(pl.col("age").is_null())用于检测 null 值。
.is_not_null()expr.is_not_null()返回非缺失值标记df.filter(pl.col("email").is_not_null())常用于过滤。
.fill_null()expr.fill_null(value_or_strategy)填充缺失值df.with_columns(pl.col("age").fill_null(0))支持 “forward”, “backward”, “mean” 等策略。
.drop_nulls()df.drop_nulls(subset=None)删除含缺失值的行df.drop_nulls(subset=["age", "score"])subset 指定检查的列。
.drop_nans()expr.drop_nans()删除 NaN(浮点特殊值)pl.col("value").drop_nans()与 null 不同,需单独处理。

6.2 处理重复值:unique(), drop_duplicates()

方法语法用途代码示例注意事项
.unique()expr.unique()返回列的唯一值df.select(pl.col("city").unique())保持首次出现顺序。
.n_unique()expr.n_unique()返回唯一值数量df.select(pl.col("id").n_unique())用于去重计数。
drop_duplicates()df.drop_duplicates(subset=None)删除重复行df.drop_duplicates(subset=["email"])subset 指定基于哪些列判断重复。
keep 参数keep="first"keep="last"指定保留哪条重复记录df.drop_duplicates(keep="last")默认 “first”。

6.3 类型转换:cast(), strict_cast()

方法语法用途代码示例注意事项
.cast()expr.cast(dtype, strict=False)转换数据类型df.with_columns(pl.col("age_str").cast(pl.Int64))若转换失败,默认转为 null。
.strict_cast()expr.strict_cast(dtype)严格类型转换pl.col("num").strict_cast(pl.Float64)转换失败会抛出异常,适合验证数据质量。
常见类型pl.Int32 / pl.Float64 / pl.Utf8 / pl.Boolean / pl.DatePolars 数据类型pl.col("price").cast(pl.Float64)使用 Polars 类型枚举更安全。

6.4 字符串处理基础:str 模块常用方法

方法语法用途代码示例注意事项
.str.to_lowercase()pl.col("col").str.to_lowercase()转小写df.select(pl.col("name").str.to_lowercase())
.str.to_uppercase()pl.col("col").str.to_uppercase()转大写df.with_columns(pl.col("tag").str.to_uppercase())
.str.contains()pl.col("col").str.contains("pattern")是否包含子串(支持正则)df.filter(pl.col("email").str.contains("@gmail.com"))默认正则模式,设 literal=True 为字面匹配。
.str.replace()str.replace("old", "new", literal=True)替换单个匹配pl.col("text").str.replace("old", "new")仅替换第一次出现。
.str.replace_all()str.replace_all("old", "new")替换所有匹配pl.col("text").str.replace_all(" ", "_")推荐用于全局替换。
.str.strip()str.strip()去除首尾空白pl.col("input").str.strip()
.str.split()str.split("delim")按分隔符拆分为列表pl.col("tags").str.split(",")返回 List 类型列。

6.5 时间日期处理基础:dt 模块常用方法

方法语法用途代码示例注意事项
.str.strptime()pl.col("col").str.strptime(pl.Date, "%Y-%m-%d")解析字符串为日期df.with_columns(pl.col("date_str").str.strptime(pl.Datetime, "%Y-%m-%d"))必须先解析才能使用 dt 模块。
.dt.year()expr.dt.year()提取年份df.select(pl.col("dob").dt.year())
.dt.month()expr.dt.month()提取月份pl.col("ts").dt.month()返回整数 1-12。
.dt.day()expr.dt.day()提取日pl.col("ts").dt.day()
.dt.hour() / .minute() / .second()expr.dt.hour()提取时间部分pl.col("ts").dt.hour()适用于 Datetime 类型。
.dt.weekday()expr.dt.weekday()返回星期几(1=Monday)pl.col("ts").dt.weekday()
.dt.truncate()expr.dt.truncate("1mo")截断到指定频率pl.col("ts").dt.truncate("1d")支持 “1h”, “1d”, “1w”, “1mo” 等。

第7章:数据操作:Filter、Sort、Sample

7.1 条件筛选:filter() 与布尔表达式

方法语法用途代码示例注意事项
filter()df.filter(condition)根据表达式筛选行df = pl.DataFrame({"name": ["A", "B", "C"], "age": [25, 30, 35]})
df.filter(pl.col("age") > 28)
推荐使用表达式风格,优于布尔索引。
比较运算符== / != / < / <= / > / >=构建基本条件pl.col("score") >= 80返回布尔表达式。
逻辑与(and)(cond1) & (cond2)多条件同时满足df.filter((pl.col("age") > 20) & (pl.col("score") < 90))必须加括号,& 优先级高。
逻辑或(or)(cond1) | (cond2)多条件任一满足df.filter((pl.col("city") == "Beijing") | (pl.col("city") == "Shanghai"))使用 | 而非 or
逻辑非(not)~(condition)取反条件df.filter(~pl.col("active").is_null())~ 表示否定。
is_in()col.is_in([values])判断是否在值列表中df.filter(pl.col("name").is_in(["Alice", "Bob"]))等价于 SQL 的 IN。

7.2 排序操作:sort()(单列与多列排序)

方法语法用途代码示例注意事项
.sort()df.sort(by, descending=False)按列排序df.sort("age")默认升序。
多列排序df.sort(["col1", "col2"], descending=[False, True])先按第一列,再按第二列df.sort(["city", "age"], descending=[False, True])descending 可为布尔值或列表。
表达式排序df.sort(pl.col("name").str.lengths())按表达式结果排序df.sort(pl.col("name").str.lengths())支持复杂逻辑。
in_placesort(..., in_place=False)是否原地修改不推荐使用 in_place=TruePolars 多数操作返回新 DataFrame。

7.3 随机抽样:sample() 与分层抽样技巧

方法语法用途代码示例注意事项
.sample(n)df.sample(n=5)随机抽取 n 行df.sample(n=3)n 超过行数时返回全部。
.sample(frac)df.sample(frac=0.5)按比例抽样df.sample(frac=0.2)frac 为浮点数,0 < frac ≤ 1。
with_replacementsample(..., with_replacement=False)是否放回抽样df.sample(n=2, with_replacement=True)放回可能重复抽取同一行。
shuffledf.sample(frac=1.0)随机打乱行序shuffled = df.sample(frac=1.0)实现 shuffle 效果。
分层抽样结合 group_by + map_groups按类别等比例抽样df.group_by("group")
.map_groups(lambda g: g.sample(n=2))
注意性能,map_groups 较慢。

第8章:列操作与特征工程

8.1 添加新列:with_columns() 与 with_column()

方法语法用途代码示例注意事项
with_columns()df.with_columns(new_exprs)添加或替换多列df.with_columns(
(pl.col("price") * pl.col("qty")).alias("total"),
pl.col("name").str.lengths().alias("name_len")
)
推荐使用,支持多个表达式。
with_column()df.with_column(expr)添加单列(已弃用)df.with_column(pl.col("age").log().alias("log_age"))建议统一使用 with_columns()
列替换同名列名若列已存在则替换df.with_columns(pl.col("age").cast(pl.Int32))不会报错,直接覆盖。

8.2 重命名列:rename() 与 alias()

方法语法用途代码示例注意事项
.rename()df.rename({"old": "new"})重命名 DataFrame 的列df.rename({"age": "age_years", "score": "grade"})接受字典映射。
.alias()expr.alias("new_name")在表达式中重命名结果列df.select(pl.col("value").log().alias("log_value"))用于 select、with_columns 中。
批量重命名rename(dict)可一次重命名多个df.rename({"a": "col1", "b": "col2"})未列出的列保持不变。

8.3 删除列:drop() 与 exclude()

方法语法用途代码示例注意事项
.drop()df.drop(["col1", "col2"])删除指定列df.drop("temp_col")支持单列名或列表。
.exclude()df.select(pl.exclude("col"))选择除指定列外的所有列df.select(pl.exclude("internal_id"))常用于排除敏感或临时列。
表达式排除pl.exclude(pl.Float64)排除特定类型列df.select(pl.exclude(pl.Boolean))支持按类型过滤。

8.4 列的算术与逻辑运算

方法语法用途代码示例注意事项
算术运算+ / - / * / / / ** / %列间计算pl.col("x") + pl.col("y")自动对齐,支持广播。
逻辑运算& / | / ~布尔逻辑(pl.col("a") > 0) & (pl.col("b") < 10)注意括号和运算符。
比较运算== / != / <生成布尔列pl.col("status") == "active"返回 Boolean 类型。
数学函数pl.col().abs() / .sqrt() / .log()常用数学变换pl.col("value").log10()支持大多数 NumPy 风格函数。

8.5 使用 when().then().otherwise() 实现条件赋值

方法语法用途代码示例注意事项
when().then()pl.when(cond).then(val)条件为真时赋值df.with_columns(
pl.when(pl.col("age") < 18)
.then("minor")
.otherwise("adult")
.alias("category")
)
类似 SQL CASE WHEN。
.otherwise().otherwise(default_val)设置默认值(else 分支)必须以 .otherwise() 结尾否则表达式不完整。
多重条件链式 when().then()实现 elif 逻辑pl.when(pl.col("score") >= 90).then("A")
.when(pl.col("score") >= 80).then("B")
.otherwise("C")
按顺序匹配,第一个为真即返回。

第9章:聚合与分组操作(GroupBy)

9.1 基本分组:group_by() 与聚合函数

方法语法用途代码示例注意事项
.group_by()df.group_by("key")按列分组df = pl.DataFrame({"city": ["A","A","B"], "sales": [100,150,200]})
df.group_by("city").agg(pl.col("sales").sum())
返回 GroupBy 对象,需接 agg。
.agg()grouped.agg(expr)执行聚合df.group_by("city").agg(pl.sum("sales"))支持表达式。
常见聚合pl.sum() / pl.mean() / pl.count() / pl.min() / pl.max()基本统计pl.mean("score")可直接用列名或表达式。

9.2 多级分组与聚合

方法语法用途代码示例注意事项
多列分组df.group_by(["col1", "col2"])按多个列组合分组df.group_by(["dept", "year"]).agg(pl.sum("salary"))分组键为组合唯一值。
聚合多列agg([expr1, expr2])一次计算多个聚合df.group_by("city").agg([
pl.sum("sales"),
pl.mean("profit")
])
提高性能,一次扫描。

9.3 使用 agg() 进行多种聚合统计

聚合函数语法用途代码示例注意事项
pl.sum()pl.sum("col")求和pl.sum("revenue")忽略 null。
pl.mean()pl.mean("col")均值pl.mean("rating")
pl.count()pl.count()pl.count("col")计数pl.count("id")pl.count() 计所有行(含 null)。
pl.n_unique()pl.n_unique("col")唯一值计数pl.n_unique("user_id")
pl.first() / pl.last()pl.first("col")取每组首/尾值pl.last("timestamp")依赖行序。
pl.list()pl.col("x").list()聚合为列表pl.col("item").list()保留组内所有值。
pl.std() / pl.var()pl.std("col")标准差与方差pl.std("value")

9.4 分组后过滤:filter() 与 having()

方法语法用途代码示例注意事项
.filter()df.group_by("key").filter(condition)先分组再过滤行(组内)df.group_by("city").filter(pl.col("sales") > 100)过滤的是原始行,非聚合后。
.having()grouped.agg(...).having(condition)过滤聚合后的组df.group_by("city")
.agg(pl.sum("sales").alias("total"))
.having(pl.col("total") > 200)
类似 SQL 的 HAVING,作用于聚合结果。

9.5 分组内排序与窗口函数初步

方法语法用途代码示例注意事项
sort_by()(agg)pl.col("x").sort_by("y")分组内按某列排序df.group_by("group").agg(pl.col("value").sort_by("score"))用于获取排序后序列。
head() / tail()pl.col("x").head(1)取每组前/后 N 个pl.col("ts").tail(1)常用于取最新记录。
rank()pl.col("x").rank()分组内排名pl.col("score").rank(method="min")支持 “average”, “min”, “dense” 等。
cumsum()pl.col("x").cumsum()累计求和(分组内)pl.col("sales").cumsum()窗口函数基础。
over()pl.col("x").sum().over("group")窗口聚合(不改变行数)df.with_columns(pl.sum("val").over("category"))返回与原表同长,适合特征工程。

第10章:连接与合并数据(Joins)

10.1 内连接、外连接、左连接、右连接

连接类型说明注意事项
内连接(inner)只保留两表键值匹配的行最常用,确保数据一致性。
左连接(left)保留左表所有行,右表无匹配则填充 null用于”主表 + 附加信息”场景。
右连接(right)保留右表所有行,左表无匹配则填充 null可通过交换左右表用左连接替代。
外连接(outer)保留两表所有行,无匹配处填充 null又称全连接(full join)。
半连接(semi)仅保留左表中在右表有匹配键的行不合并数据,仅过滤。
反连接(anti)仅保留左表中在右表无匹配键的行用于查找”缺失关联记录”。

10.2 使用 join() 方法进行 DataFrame 合并

方法语法用途代码示例注意事项
.join()df1.join(df2, on="key", how="inner")按键合并两个 DataFramedf1 = pl.DataFrame({"id": [1,2], "name": ["A","B"]})
df2 = pl.DataFrame({"id": [1,3], "age": [25,30]})
df1.join(df2, on="id", how="left")
on 指定连接键;how 指定连接类型。
how 参数how="inner" / "left" / "outer" / "semi" / "anti"控制连接行为df1.join(df2, on="id", how="outer")默认为 “inner”。
多键连接on=["key1", "key2"]使用多个列作为连接键df1.join(df2, on=["dept", "year"])所有键必须同时匹配。

10.3 连接键的选择与重复列处理

方法语法用途代码示例注意事项
on 参数join(..., on="col")指定同名列作为连接键df1.join(df2, on="user_id")两表必须都有该列。
left_on / right_onjoin(left_on="col1", right_on="col2")指定不同名的连接键df1.join(df2, left_on="uid", right_on="user_id")用于列名不一致时。
suffix 参数suffix="_right"解决重复列名冲突df1.join(df2, on="id", suffix="_right")默认为 “_right”,避免覆盖。
预处理重命名df2.rename({"value": "value_y"})手动控制列名先重命名再连接更灵活,推荐复杂场景使用。

10.4 使用 concatenate() 合并行(上下拼接)

方法语法用途代码示例注意事项
pl.concat()pl.concat([df1, df2], how="vertical")垂直拼接多个 DataFramedf1 = pl.DataFrame({"a": [1], "b": [2]})
df2 = pl.DataFrame({"a": [3], "b": [4]})
pl.concat([df1, df2])
默认 how="vertical",要求列名和类型兼容。
how="horizontal"pl.concat([df1, df2], how="horizontal")水平拼接(按列合并)pl.concat([df1, df3], how="horizontal")类似 pd.concat(..., axis=1),需行数相同。
how="diagonal"pl.concat([df1, df2], how="diagonal")对角拼接,自动对齐列pl.concat([df1, df2], how="diagonal")适用于列部分重叠的表。
列不匹配处理require_same_dtype=False允许类型不同(会提升)pl.concat([df1, df2], require_same_dtype=False)谨慎使用,可能导致精度损失。

第11章:宽长格式转换(Pivoting & Melting)

11.1 将宽表转为长表:melt()

方法语法用途代码示例注意事项
.melt()df.melt(id_vars, value_vars, variable_name, value_name)将多列转为键值对形式df = pl.DataFrame({"city": ["A","B"], "2023": [100,150], "2024": [110,160]})
df.melt(id_vars="city", value_vars=["2023","2024"], variable_name="year")
用于时间序列或指标列转换。
id_varsid_vars="col"["col1"]保持不变的标识列id_vars="subject"通常为维度列。
value_varsvalue_vars=["v1","v2"]要转换的值列可省略,自动选择非 id_vars 列建议显式指定。
variable_name / value_name自定义新列名控制输出列名variable_name="year", value_name="sales"默认为 “variable” 和 “value”。

11.2 将长表转为宽表:pivot()

方法语法用途代码示例注意事项
.pivot()df.pivot(values, index, columns, aggregate_function)将长表重塑为宽表df = pl.DataFrame({"city": ["A","A","B"], "year": ["2023","2024","2023"], "sales": [100,110,150]})
df.pivot(values="sales", index="city", columns="year")
类似 Excel 数据透视表。
valuesvalues="col"作为值填充的列values="score"必须为数值或可存储类型。
indexindex="row_key"作为行索引的列index="student"
columnscolumns="col_key"作为新列名的列columns="subject"唯一值将成为列名。
aggregate_functionaggregate_function="mean"处理重复单元格aggregate_function="sum"默认报错,可设 “first”, “mean” 等。

11.3 使用 pivot 进行交叉表统计

方法语法用途代码示例注意事项
交叉表(crosstab)df.pivot(values, index, columns, aggregate_function="count")统计类别组合频次df.pivot(values="index", index="gender", columns="status", aggregate_function="count")values 可为任意列(常用索引)。
多值聚合结合 with_columns添加总计行/列先 pivot,再用 sum 计算Polars 不直接支持,需后处理。
布尔交叉表pl.lit(1) 作为值构建存在性标记表df.with_columns(pl.lit(1).alias("present")).pivot(...)用于标记是否发生。

第12章:表达式(Expressions)编程范式

12.1 什么是表达式(Expression)?

概念说明注意事项
表达式(Expression)一个描述数据操作的惰性对象,如 pl.col("age") + 1不立即执行,可组合、优化。
惰性求值表达式在 collect() 或触发时才计算Lazy 模式下可优化执行计划。
函数式风格表达式是纯函数,无副作用易于测试和组合。
核心优势支持谓词下推、列投影、自动并行性能优于命令式循环。

12.2 常用表达式构建:col(), lit(), when().then() 等

方法语法用途代码示例注意事项
pl.col()pl.col("name")引用列pl.col("price") * 1.1支持字符串、正则 r"^prefix"
pl.lit()pl.lit(100)创建标量值表达式pl.col("x") + pl.lit(5)将 Python 值嵌入表达式。
pl.when().then()pl.when(cond).then(val)条件逻辑见第 8.5 节核心控制流工具。
pl.all() / pl.any()pl.all() / pl.any(pl.Boolean)聚合布尔表达式pl.when(pl.all(pl.col("x") > 0)).then("positive")pl.all() 检查所有行为真。

12.3 表达式的组合与嵌套

方法语法用途代码示例注意事项
算术组合(expr1 + expr2) * expr3数学运算(pl.col("a") + pl.col("b")) / 2支持标准运算符。
逻辑组合(cond1) & (cond2)布尔逻辑(pl.col("age") > 18) & (pl.col("active"))必须加括号。
函数嵌套f(g(h(x)))多层变换pl.col("email").str.strip().str.to_lowercase()链式调用,从左到右执行。
列表表达式[expr1, expr2]批量操作df.select([pl.sum("x"), pl.mean("y")])在 select, with_columns 中常用。

12.4 在 select、with_columns、filter 中使用表达式

上下文用法代码示例注意事项
select()选择列或表达式结果df.select(pl.col("name").str.lengths())只保留表达式结果列。
with_columns()添加/替换列df.with_columns(pl.col("age").log().alias("log_age"))保留原列,新增表达式列。
filter()筛选行df.filter(pl.col("score") >= pl.mean("score"))表达式返回布尔 Series。
group_by().agg()聚合计算df.group_by("cat").agg(pl.sum("val"))表达式在每组内计算。
sort()按表达式排序df.sort(pl.col("name").str.lengths())支持复杂排序键。

第13章:惰性计算(Lazy Evaluation)

13.1 LazyFrame 简介与创建

概念语法用途代码示例注意事项
LazyFramepl.LazyFrame()df.lazy()惰性 DataFrame,不立即执行df = pl.DataFrame({"a": [1,2,3], "b": [4,5,6]})
lazy_df = df.lazy()
所有操作返回 LazyFrame,延迟计算。
从文件创建pl.scan_csv("data.csv")惰性读取文件lazy_df = pl.scan_csv("sales.csv")不加载数据到内存,仅记录读取计划。
支持的扫描方法scan_csv() / scan_parquet() / scan_ipc()惰性读取各种格式pl.scan_parquet("data.parquet")适用于大文件,支持谓词下推。

13.2 惰性操作链的构建

方法语法用途代码示例注意事项
链式操作lazy_df.filter(...).group_by(...).agg(...)构建处理流水线result = (pl.scan_csv("log.csv")
.filter(pl.col("status") == "success")
.group_by("user_id")
.agg(pl.sum("amount")))
每步返回 LazyFrame,无实际计算。
惰性兼容方法select() / with_columns() / sort() / join()大多数操作支持惰性模式同上避免使用 .apply() 等强制求值操作。
谓词下推自动优化将过滤条件下推到读取阶段pl.scan_csv("data.csv").filter(pl.col("age") > 30)仅读取满足条件的块,节省 I/O。
列投影自动优化只读取后续需要的列pl.scan_csv("data.csv").select(["name", "age"])减少内存占用。

13.3 执行计划查看:explain()

方法语法用途代码示例注意事项
.explain()lazy_df.explain()查看执行计划(文本)print(lazy_df.explain())显示优化后的逻辑计划和物理计划。
optimized 参数explain(optimized=True)控制是否显示优化后计划lazy_df.explain(optimized=False)调试时可对比优化前后差异。
执行成本提示输出中包含 file_scan / filter / aggregate 等识别性能瓶颈关注扫描范围、聚合方式帮助判断是否触发了谓词/列下推。

13.4 触发计算:collect() 与 collect_async()

方法语法用途代码示例注意事项
.collect()lazy_df.collect()触发计算,返回 DataFramedf = lazy_df.collect()实际执行所有惰性操作。
错误处理可能抛出 ComputeError数据问题在 collect 时暴露用 try-except 包裹建议在 collect 时验证数据质量。
collect_async()await lazy_df.collect_async()异步收集(需 asyncio)import asyncio
async def run():
df = await lazy_df.collect_async()
return df
提升 I/O 密集型任务的吞吐量。
性能建议在链的末尾调用避免多次 collect构建完整流水线后一次性 collect减少重复计算。

第14章:性能优化与最佳实践

14.1 避免 Python 循环:使用向量化操作

方法语法用途代码示例注意事项
向量化表达式pl.col("x") + pl.col("y")替代 for 循环df.with_columns((pl.col("a") * pl.col("b")).alias("product"))Polars 在 Rust 层优化执行。
避免 .apply() / .map()尽量不用强制逐元素执行 Python 函数使用 pl.when().then() 或数学表达式替代性能极低,破坏惰性优化。
使用内置聚合pl.sum() / pl.mean()高效统计df.group_by("key").agg(pl.sum("value"))比自定义函数快数十倍。

14.2 合理使用字符串与分类类型(Categorical)

方法语法用途代码示例注意事项
cast(pl.Categorical)pl.col("col").cast(pl.Categorical)将低基数字符串转为分类类型df.with_columns(pl.col("city").cast(pl.Categorical))节省内存,加速分组、连接。
字符串 vs 分类pl.Utf8 vs pl.Categorical存储与性能权衡对 “gender”, “status” 等列使用分类高基数(如姓名)不适合。
内存优势分类类型存储整数索引显著减少内存占用百万行文本列可节省 90%+ 内存尤其适合重复值多的列。

14.3 内存管理与数据类型优化

方法语法用途代码示例注意事项
最小够用原则pl.Int8 / pl.Int16 / pl.Float32使用最小必要精度df.with_columns(pl.col("age").cast(pl.Int8))避免默认 Int64 浪费内存。
.memory_usage()df.memory_usage()查看每列内存占用df.with_columns(pl.col("x").cast(pl.Float32)).memory_usage()诊断内存瓶颈。
及时释放变量del df / gc.collect()手动管理内存处理大表后删除引用Python 垃圾回收不即时。

14.4 并行执行与多线程设置

方法语法用途代码示例注意事项
Polars 自动并行默认启用多核执行聚合、连接等无需额外代码基于 Rayon 线程池,开箱即用。
设置线程数pl.Config.set_parallelism("rayon") 或环境变量控制并发线程export POLARS_MAX_THREADS=4避免过度占用资源。
I/O 与计算分离collect_async()异步 I/O + 并行计算结合异步框架使用提升整体吞吐。
GIL 绕过Rust 后端不受 Python GIL 限制所有表达式操作真正的并行计算。

第15章:高级功能与扩展

15.1 自定义函数(UDF)与 map_elements()

方法语法用途代码示例注意事项
.map_elements()pl.col("x").map_elements(func)对元素应用 Python 函数def square(x): return x ** 2
df.with_columns(pl.col("a").map_elements(square))
破坏性能,仅在必要时使用。
类型注解returns=pl.Int64帮助 Polars 推断返回类型.map_elements(f, returns=pl.Float64)避免类型错误。
替代方案使用表达式组合尽量避免 UDF(pl.col("a") ** 2)表达式更快更安全。

15.2 窗口函数(Window Functions)

方法语法用途代码示例注意事项
.over()expr.over("group")分组内窗口计算pl.col("score").rank().over("class")不改变行数,适合特征工程。
排名函数rank() / dense_rank() / row_number()分组内排序pl.col("val").rank(method="min").over("cat")支持多种排名策略。
累计函数cumsum() / cummax() / cumcount()累计统计pl.col("x").cumsum().over("group")按组内顺序累计。
移动窗口rolling() 结合 over滚动统计pl.col("price").rolling_mean(3).over("stock")需先排序。

15.3 结构体与嵌套数据处理

方法语法用途代码示例注意事项
struct 类型pl.Struct存储嵌套字段pl.struct([pl.col("a"), pl.col("b")]).alias("pair")类似字典或 JSON 对象。
解构结构体.struct.field("name")提取子字段pl.col("pair").struct.field("a")支持链式访问。
处理列表列list 类型 + arr 模块操作数组pl.col("items").list.lengths()适用于 JSON 数组字段。

15.4 与 NumPy、Pandas 的互操作

方法语法用途代码示例注意事项
转 Pandas.to_pandas()导出为 DataFramepdf = df.to_pandas()大数据集可能内存不足。
从 Pandaspl.DataFrame(pdf)导入 Pandas 数据df = pl.DataFrame(pd_df)自动转换类型。
转 NumPy.to_numpy()转为数组(单列)arr = df["col"].to_numpy()多列需先 select 或 to_dict()
共享内存零拷贝转换(部分支持)减少内存复制df.to_pandas(use_pyarrow=True)推荐使用 PyArrow 作为桥梁。

15.5 使用 Polars 进行大数据处理(与 DuckDB 集成)

方法语法用途代码示例注意事项
DuckDB 读取pl.read_database()从 DuckDB 查询加载df = pl.read_database("SELECT * FROM tbl", connection)适用于超大表的预聚合。
Polars 写入 DuckDBdf.write_database()将结果存入数据库df.write_database("table_name", connection)实现 ETL 流水线。
混合使用Polars 处理 + DuckDB 查询各取所长用 Polars 清洗,DuckDB 做复杂 SQLDuckDB 支持 Parquet 直接查询。
性能优势列式存储 + 向量化引擎处理 GB~TB 级数据结合 scan_parquet + collect()适合本地大数据分析场景。