如何在Polars LazyFrame中按列名模式选择多列并生成计算表达式
我太懂这种纠结了——想用LazyFrame的延迟计算优势,又要按列名模式批量做运算,还得避开那个烦人的列名解析性能警告。其实Polars的表达式和选择器系统已经给我们准备好了非常灵活的解决方案,完全不用硬啃df.columns。
下面给你两种实用的方法,都能完美解决你的需求:
方法一:用选择器(Selectors)动态生成表达式(推荐)
这种方法完全不需要提前获取列名,直接利用Polars的selectors匹配列模式,然后动态生成运算表达式,从根源上避免性能警告。
针对你的场景(给每个_low列匹配对应的_high列并相加),代码可以这么写:
import polars as pl from polars import selectors as cs # 你的原始LazyFrame df = pl.from_repr(""" shape: (5, 4) ┌─────────┬──────────┬───────────┬────────────┐ │ red_low ┆ red_high ┆ green_low ┆ green_high │ │ --- ┆ --- ┆ --- ┆ --- │ │ i64 ┆ i64 ┆ i64 ┆ i64 │ ╞═════════╪══════════╪═══════════╪════════════╡ │ 1 ┆ 10 ┆ 2 ┆ 20 │ │ 2 ┆ 20 ┆ 3 ┆ 30 │ │ 3 ┆ 30 ┆ 4 ┆ 40 │ │ 4 ┆ 40 ┆ 5 ┆ 50 │ │ 5 ┆ 50 ┆ 6 ┆ 60 │ └─────────┴──────────┴───────────┴────────────┘ """).lazy() # 1. 用选择器匹配所有以_low结尾的列 low_columns = cs.ends_with("_low") # 2. 对每个匹配到的列,动态生成"_low + _high"的表达式 sum_expressions = low_columns.map( lambda col: (col + pl.col(col.name.replace("_low", "_high"))).alias(col.name.replace("_low", "_sum")) ) # 3. 将新列添加到原DataFrame并执行计算 result = df.with_columns(sum_expressions).collect() print(result)
运行后就会得到你想要的结果,而且全程不会触发性能警告——因为我们完全是在表达式层面处理,没有提前解析LazyFrame的列名集合。
方法二:从Schema安全提取列名(适合需要自定义前缀逻辑的场景)
如果你需要更复杂的前缀处理逻辑(比如列名的分隔符不是_,或者有特殊前缀规则),可以从LazyFrame的schema属性提取列名。这里要注意:只要你的LazyFrame有明确的Schema(比如从已知结构的数据源创建,或手动指定了Schema),访问schema不会触发性能警告——只有当Schema需要动态解析时(比如从无Schema的CSV读取)才会有问题。
示例代码:
# 从Schema中提取所有列名(安全操作,无性能警告) all_column_names = list(df.schema.keys()) # 提取所有唯一的前缀(比如red、green) prefixes = {name.rsplit("_", 1)[0] for name in all_column_names if "_" in name} # 为每个前缀生成相加表达式 sum_expressions = [] for prefix in prefixes: sum_expressions.append( (pl.col(f"{prefix}_low") + pl.col(f"{prefix}_high")).alias(f"{prefix}_sum") ) # 执行计算 result = df.with_columns(sum_expressions).collect() print(result)
这种方法的优势是前缀逻辑可以完全自定义,比如你可以用正则表达式提取前缀,或者过滤特定前缀的列。
为什么这两种方法比直接用df.columns好?
直接调用df.columns会触发Polars的性能警告,因为它需要强制解析LazyFrame的执行计划来确定列名——而上面两种方法要么完全在表达式/选择器层面处理,要么利用了LazyFrame自带的Schema元数据,不会触发不必要的计划解析,完美保留了LazyFrame的延迟计算优势。
备注:内容来源于stack exchange,提问作者Jay Miller

