Polars按列名前缀分组指定列的实现问题(替代Pandas写法)
Polars按列名前缀分组的正确实现方式
现有如下DataFrame,除首列position外,其余列均以.0和.1后缀成对出现。需要通过提取列名中.前的前缀,对这些列按列分组并进行聚合操作。Pandas中已有可行实现,但Polars中尝试多种写法均报错,现求正确实现方式。
示例DataFrame
position 1164_1164.0 1164_1164.1 yes_001.0 yes_001.1 10316.0 10316.1 10349.0 10349.1 10418.0 10418.1 4414 0 1 0 0 1 0 0 0 1 1 5295 0 1 0 0 1 0 0 0 1 1 5738 0 1 0 0 1 0 0 0 1 1 5785 0 1 0 0 1 0 0 0 1 1 6392 0 1 0 0 1 0 0 0 1 1 7727 1 1 0 0 1 0 0 0 1 1 8876 1 1 0 0 1 0 0 0 1 1 9018 1 1 0 0 1 0 0 0 1 1 9208 1 1 0 0 1 0 1 0 1 1 9627 1 1 0 0 1 0 1 0 1 0
Pandas实现代码
g = df.iloc[:,1:].groupby(df.columns[1:].str.extract(r'(\w+)\.', expand=False), axis=1) # 后续可通过g.sum()等操作完成聚合
Polars尝试的错误写法及报错
- 错误写法1:直接对列名列表调用
str.extractg = df[:,1:].groupby(df.columns[1:]) # 尝试给df.columns[1:]加str.extract时报错:AttributeError: 'list' object has no attribute 'str' - 错误写法2:用
pl.col("*").str.extract分组g = df[:,1:].groupby(pl.col("*").str.extract(r'(\w+)\.')) # 执行sum聚合时报错:DuplicateError: column with name '1164_1164.0' has more than one occurrences
正确的Polars实现方式
方法一:批量列选择+聚合
直接通过列名前缀筛选列,批量完成聚合:
import polars as pl # 获取除首列外的所有列 target_cols = df.columns[1:] # 提取所有唯一前缀 prefixes = {col.split('.')[0] for col in target_cols} # 按前缀分组求和,保留position列 result = df.select( pl.col("position"), *[ pl.col([col for col in target_cols if col.startswith(prefix)]).sum().alias(prefix) for prefix in prefixes ] )
方法二: melt+groupby+pivot(灵活适配复杂聚合)
将宽表转长表后分组,再转回宽表,适合多类型聚合场景:
import polars as pl # 转长格式,保留position作为标识列 melted_df = df.melt(id_vars="position", var_name="col_name", value_name="value") # 提取列名前缀 melted_df = melted_df.with_columns( pl.col("col_name").str.extract(r'^(.+?)\.', 1).alias("prefix") ) # 按position和前缀分组求和,再转回宽格式 result = melted_df.groupby(["position", "prefix"]).agg( pl.col("value").sum() ).pivot( index="position", columns="prefix", values="value" )
方法三:列名映射分组
通过字典映射列名到前缀,再批量聚合:
import polars as pl # 生成列名到前缀的映射字典 col_prefix_map = {col: col.split('.')[0] for col in df.columns[1:]} # 获取唯一前缀 unique_prefixes = set(col_prefix_map.values()) # 按前缀聚合 result = df.select( pl.col("position"), *[ pl.col([k for k, v in col_prefix_map.items() if v == prefix]).sum().alias(prefix) for prefix in unique_prefixes ] )
内容的提问来源于stack exchange,提问作者guidebortoli
相关产品推荐
相关产品推荐

