在Polars中处理结构化数据时,经常需要根据某一列的现有值去匹配字典的键,筛选出字典中存在对应键的行,或者筛选出字典中对应值满足特定条件的行。这种需求如果采用Python循环逐行判断的方式实现,会严重拖慢处理速度,无法发挥Polars的高性能优势。

基础场景:筛选列值存在于字典键中的行
假设我们有一个存储用户信息的DataFrame,同时有一个记录有效用户ID的字典,需要筛选出ID在字典键中的用户数据。最直观的高效方式是利用Polars的is_in表达式,先将字典的键转换为列表传入判断逻辑。
import polars as pl
# 构造示例数据
user_df = pl.DataFrame({
"user_id": [1001, 1002, 1003, 1004, 1005],
"user_name": ["张三", "李四", "王五", "赵六", "钱七"],
"score": [88, 92, 75, 90, 85]
})
# 有效用户ID字典,键为用户ID,值为用户等级
valid_user_dict = {1001: "A", 1003: "B", 1005: "A"}
# 提取字典键列表
valid_ids = list(valid_user_dict.keys())
# 筛选user_id在valid_ids中的行
filtered_df = user_df.filter(pl.col("user_id").is_in(valid_ids))
print(filtered_df)
进阶场景:根据字典键值条件筛选行
如果需要进一步根据字典键对应的值做筛选,比如只保留字典中对应等级为A的用户,可以在上述基础上增加映射步骤,通过map_dict方法将列值映射为字典对应的值,再添加判断条件。
# 方法1:先映射再筛选
filtered_df_v2 = user_df.with_columns(
pl.col("user_id").map_dict(valid_user_dict).alias("user_level")
).filter(
pl.col("user_level") == "A"
).drop("user_level")
print(filtered_df_v2)
# 方法2:直接构造判断表达式
filtered_df_v3 = user_df.filter(
pl.col("user_id").map_dict(valid_user_dict) == "A"
)
print(filtered_df_v3)
大规模数据场景:使用join替代字典映射
当字典数据量较大,或者需要多次进行字典匹配操作时,将字典转换为Polars的DataFrame再进行join操作,性能会比直接使用map_dict更优,因为join操作能更好地利用Polars的查询优化器。
# 将字典转换为DataFrame
valid_df = pl.DataFrame({
"user_id": list(valid_user_dict.keys()),
"user_level": list(valid_user_dict.values())
})
# 通过join筛选等级为A的用户
filtered_df_v4 = user_df.join(
valid_df.filter(pl.col("user_level") == "A"),
on="user_id",
how="inner"
)
print(filtered_df_v4)
不同方法对比
以下是几种常见实现方式的适用场景和性能对比:
| 实现方式 | 适用场景 | 性能表现 |
|---|---|---|
| is_in+字典键列表 | 仅判断列值是否在字典键中,不需要使用字典值 | 优,无额外映射开销 |
| map_dict+条件判断 | 字典数据量小,需要用到字典对应值做判断 | 良好,小数据量下差异不明显 |
| join字典DataFrame | 字典数据量大,或需要多次匹配字典数据 | 最优,大数据量下优势明显 |
注意事项
- 使用
map_dict时,如果列值不在字典键中,默认会返回null,需要提前处理缺失值避免筛选逻辑出错。 - 字典的键类型需要和DataFrame对应列的类型完全一致,否则会出现匹配失败的情况。
- 如果筛选逻辑非常复杂,不建议强行用表达式实现,可以适当拆分步骤,保证代码可读性的同时兼顾性能。
Polars数据筛选字典键列值处理DataFrame操作修改时间:2026-06-19 22:06:18