如何在Polars中创建带百分比的交叉表?解决代码生成器类型错误
解决Polars交叉表百分比转换的TypeError问题
错误原因:
crosstab.select()无法直接处理生成器对象,当同时传入索引列表达式和生成器时,Polars会抛出类型错误。单独调用时能运行是因为Polars对单个可迭代参数做了兼容,但多参数场景不支持。快速修复:将生成器转换为列表,修改调用代码:
crosstab.select(cs.by_index(0), *list(perc_cols(crosstab)))
或者先把表达式整理成列表再传入:
exprs = [cs.by_index(0)] + list(perc_cols(crosstab)) crosstab.select(exprs)
- 优化实现(更贴合Polars原生风格,避免转numpy):
原函数依赖numpy计算总和,改用Polars原生的水平求和方法,更高效且无需类型转换:
def perc_cols(df): # 计算每行的总和(排除第一列索引) row_total = pl.sum_horizontal(df.columns[1:]) for col in df.columns[1:]: # 可选保留两位小数提升可读性 yield (pl.col(col) / row_total * 100).round(2)
- 完整可运行示例:
import polars as pl import polars.selectors as cs df = pl.DataFrame({"a": [2, 0, 1, 0, 0, 0], "b": [1, 1, 1, 0, 0, 1]}) crosstab = ( df.pivot(on="b", index="a", values="b", aggregate_function="len", sort_columns=True) .fill_null(0) .sort("a") ) def perc_cols(df): row_total = pl.sum_horizontal(df.columns[1:]) for col in df.columns[1:]: yield (pl.col(col) / row_total * 100).round(2) result = crosstab.select(cs.by_index(0), *list(perc_cols(crosstab))) print(result)
运行输出:
shape: (3, 3) ┌─────┬──────────┬──────────┐ │ a ┆ 0 ┆ 1 │ │ --- ┆ --- ┆ --- │ │ i64 ┆ f64 ┆ f64 │ ╞═════╪══════════╪══════════╡ │ 0 ┆ 33.33 ┆ 66.67 │ │ 1 ┆ 0.0 ┆ 100.0 │ │ 2 ┆ 0.0 ┆ 100.0 │ └─────┴──────────┴──────────┘
内容的提问来源于stack exchange,提问作者robertspierre
相关产品推荐
相关产品推荐

