
本文介绍使用 polars 的字符串提取、字符清理与表达式运算,将含 si 前缀(k/m/b)的字符串列(如 "1.2k"、"-1.2b")高效转换为对应浮点数值。方法无需 python udf,全程向量化,兼顾精度与性能。
本文介绍使用 polars 的字符串提取、字符清理与表达式运算,将含 si 前缀(k/m/b)的字符串列(如 "1.2k"、"-1.2b")高效转换为对应浮点数值。方法无需 python udf,全程向量化,兼顾精度与性能。
在数据处理中,常遇到以 SI 单位前缀(如 k 表示千、M 表示百万、B 表示十亿)简写的数值字符串(例如 "1.2k"、"-3.5M")。Polars 提供了高性能、纯表达式的解决方案,避免使用慢速的 apply() 或 map_elements()。
核心思路分为三步:
- 提取纯数字部分:用 str.strip_chars('KMB') 移除后缀字母(注意大小写敏感,此处需统一处理);
- 提取前缀标识:用正则 str.extract(r'(k|K|m|M|b|B)') 捕获前缀,并映射为对应幂次(k/K → 3, m/M → 6, b/B → 9);
- 组合计算:将数字部分转为浮点数,乘以 10^power 得到最终值。
以下是完整、健壮的实现(已适配大小写,并修复原答案中 Float32 精度不足及未处理小写前缀的问题):
import polars as pl
df = pl.DataFrame(dict(j=['1.2', '1.2k', '1.2M', '-1.2B', '3.5K', '0.75m']))
# 统一转小写便于匹配,提取前缀并映射幂次
prefix_power = (
pl.col('j')
.str.to_lowercase()
.str.extract(r'(k|m|b)')
.replace({'k': 3, 'm': 6, 'b': 9})
.fill_null(0)
)
# 提取数字部分(保留符号和小数点),转 float64 保证精度
numeric_part = (
pl.col('j')
.str.replace(r'[kKmMbB]$', '') # 安全移除末尾前缀(仅一次)
.cast(pl.Float64)
)
# 合并:数值 × 10^幂次
df_parsed = df.with_columns(
(numeric_part * (10 ** prefix_power)).alias('j')
)
print(df_parsed)
输出:
shape: (6, 1) ┌─────────────┐ │ j │ │ --- │ │ f64 │ ╞═════════════╡ │ 1.2 │ │ 1200.0 │ │ 1200000.0 │ │ -1200000000.0 │ │ 3500.0 │ │ 750000.0 │ └─────────────┘
✅ 关键注意事项:
- 使用 str.replace(r'[kKmMbB]$', '') 比 strip_chars() 更精准,避免误删中间字符(如 "1.2kb" 中的 k);
- 显式 .cast(pl.Float64) 防止默认 Float32 导致大数精度丢失(如 1.2e9 可能变成 1.2000001e9);
- fill_null(0) 确保无前缀字符串(如 "1.2")按 10⁰ = 1 计算,保持原值;
- 若需支持 G(giga)、T(tera)或 µ(micro),只需扩展 replace 映射字典即可。
该方案完全向量化、零 Python 循环,适用于百万级数据,是 Polars 解析工程化文本数值的标准实践。










