如何在Polars中将指定列按自定义格式拼接为新的字符串列
如何在Polars中将指定列按自定义格式拼接为新的字符串列
我明白你想要实现的效果——把Total列用括号包裹,再和percentage列拼接,最后加上百分号,形成(Total) percentage%这样的新列。你之前尝试的几种方法没成功,核心问题是误用了Python原生的字符串拼接逻辑,把Polars的列对象直接转成了字符串,而不是对列内的每行数据做操作。
正确解法:使用Polars的pl.format函数
Polars提供了pl.format这个专门用于格式化字符串列的工具,它的用法和Python原生的str.format非常相似,能完美满足你的需求:
import polars as pl pl.Config(tbl_rows=21) # 保持原配置 so_df = pl.from_repr(""" ┌──────────────┬─────────────────────┬─────┬───────┬────────────┬────────┐ │ Flag ┆ Category ┆ len ┆ Total ┆ percentage ┆ value │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ i64 ┆ i64 ┆ f64 ┆ f64 │ ╞══════════════╪═════════════════════╪═════╪═══════╪════════════╪════════╡ │ Outof Range ┆ Thyroid ┆ 7 ┆ 21 ┆ 33.33 ┆ 33.33 │ │ Outof Range ┆ Inflammatory Marker ┆ 2 ┆ 8 ┆ 25.0 ┆ 25.0 │ │ Outof Range ┆ Lipid ┆ 12 ┆ 63 ┆ 19.05 ┆ 19.05 │ │ Outof Range ┆ LFT ┆ 14 ┆ 87 ┆ 16.09 ┆ 16.09 │ │ Outof Range ┆ DLC ┆ 11 ┆ 126 ┆ 8.73 ┆ 8.73 │ │ Outof Range ┆ Vitamin ┆ 1 ┆ 14 ┆ 7.14 ┆ 7.14 │ │ Outof Range ┆ CBC ┆ 2 ┆ 45 ┆ 4.44 ┆ 4.44 │ │ Outof Range ┆ KFT ┆ 2 ┆ 56 ┆ 3.57 ┆ 3.57 │ │ Outof Range ┆ Urine Examination ┆ 1 ┆ 28 ┆ 3.57 ┆ 3.57 │ │ Within Range ┆ Thyroid ┆ 14 ┆ 21 ┆ 66.67 ┆ -66.67 │ │ Within Range ┆ Inflammatory Marker ┆ 6 ┆ 8 ┆ 75.0 ┆ -75.0 │ │ Within Range ┆ Lipid ┆ 51 ┆ 63 ┆ 80.95 ┆ -80.95 │ │ Within Range ┆ LFT ┆ 73 ┆ 87 ┆ 83.91 ┆ -83.91 │ │ Within Range ┆ DLC ┆ 115 ┆ 126 ┆ 91.27 ┆ -91.27 │ │ Within Range ┆ Vitamin ┆ 13 ┆ 14 ┆ 92.86 ┆ -92.86 │ │ Within Range ┆ CBC ┆ 43 ┆ 45 ┆ 95.56 ┆ -95.56 │ │ Within Range ┆ KFT ┆ 54 ┆ 56 ┆ 96.43 ┆ -96.43 │ │ Within Range ┆ Urine Examination ┆ 27 ┆ 28 ┆ 96.43 ┆ -96.43 │ │ Within Range ┆ Anemia ┆ 38 ┆ 38 ┆ 100.0 ┆ -100.0 │ │ Within Range ┆ Diabetes ┆ 22 ┆ 22 ┆ 100.0 ┆ -100.0 │ │ Within Range ┆ Electrolyte ┆ 46 ┆ 46 ┆ 100.0 ┆ -100.0 │ └──────────────┴─────────────────────┴─────┴───────┴────────────┴────────┘ """) # 生成目标列 so_df = so_df.with_columns( labels_value=pl.format("({}) {}%", pl.col("Total"), pl.col("percentage")) ) # 查看结果(仅展示新列和部分原列) print(so_df.select("Flag", "Category", "labels_value").head(5))
运行后,labels_value列的结果会完全符合你的预期:
┌─────────────┬─────────────────────┬──────────────┐ │ Flag ┆ Category ┆ labels_value │ │ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str │ ╞═════════════╪═════════════════════╪══════════════╡ │ Outof Range ┆ Thyroid ┆ (21) 33.33% │ │ Outof Range ┆ Inflammatory Marker ┆ (8) 25.0% │ │ Outof Range ┆ Lipid ┆ (63) 19.05% │ │ Outof Range ┆ LFT ┆ (87) 16.09% │ │ Outof Range ┆ DLC ┆ (126) 8.73% │ └─────────────┴─────────────────────┴──────────────┘
额外技巧:控制小数位数
如果需要对percentage的小数位数做统一控制(比如强制保留两位小数),可以在格式字符串里指定精度:
so_df = so_df.with_columns( labels_value=pl.format("({}) {:.2f}%", pl.col("Total"), pl.col("percentage")) )
这样25.0会被格式化为25.00%,确保所有行的小数位数一致。
为什么你之前的方法失败了?
- 第一种方法:
"("+str(pl.col("Total"))+") "+str(pl.col("percentage"))+"%"
这里str(pl.col("Total"))得到的是列对象的字符串表示<Expr ['Total']>,而不是列内的实际数值,拼接后会生成固定的错误字符串,而非每行对应的值。 - 第二种方法:
"".join([...])
同理,join的是列对象的字符串形式,不是每行的数值,结果自然不对。 - 第三种方法:
pl.concat_str([pl.col("Total"),pl.col("percentage")])
只是简单拼接两列的字符串,没有添加括号和百分号,不符合格式要求。
备注:内容来源于stack exchange,提问作者ViSa
相关产品推荐
相关产品推荐

