最可靠的方法是使用 pint 库解析和转换带单位的字符串,它内置1700+单位、支持复合与中文单位、上下文感知,并可与 pandas 集成实现单位感知计算。

用 pint 解析和转换带单位的字符串最可靠
直接用正则或 float() 拆解 "2.5 m/s" 这类字符串,很快会掉进空格、指数、复合单位(如 "kg·m²/s²")、Unicode 中文单位(如 "毫秒")的坑里。推荐用 pint —— 它专为物理量建模,内置 1700+ 单位定义,支持自定义单位和上下文(如温度转换需区分 ΔT 和绝对温标)。
安装后初始化一次即可:
from pint import UnitRegistry ureg = UnitRegistry() Q_ = ureg.Quantity
解析字符串示例:
2.5 meter / second
- 别用
ureg.parse_expression("2.5 * m / s"):它不接受空格,且易受变量名污染 - 中文单位需提前注册,比如
ureg.define("毫秒 = millisecond = ms") -
q.magnitude是纯数值,q.units是单位对象,二者必须一起传,不能只存数字再“脑补”单位
用 pandas + pint 处理带单位的列
原生 pandas 不支持单位,但 pint-pandas 扩展能让 Series 和 DataFrame 保存 Quantity 对象,保留单位语义并支持向量化运算。
安装扩展:
pip install pint-pandas
创建带单位的列:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
import pandas as pd
df = pd.DataFrame({
"velocity": [Q_("10 m/s"), Q_("25 km/h"), Q_("0.5 mile/min")]
})
# 自动统一为基本单位(meter / second),支持 df["velocity"].mean()、df["velocity"] > Q_("5 m/s")
- 读 CSV 时单位是字符串列?先用
df["val"].apply(Q_)转换,别用astype - 算术操作(如
df["a"] + df["b"])会自动检查单位兼容性,不匹配直接报DimensionalityError - 导出前务必调用
.to("m/s").magnitude提取数值,否则to_csv会写入对象地址或触发__str__不可控输出
避免单位丢失的三个关键时机
单位不是装饰,是数据类型的一部分;一旦丢掉,就不可逆。
- 从 Excel/CSV 读入时:用
pd.read_csv(..., dtype={"temp": str})防止 pandas 把"25 °C"当数字强转成25.0 - 做聚合(
groupby().mean())后:结果仍是Quantity,但若中间用了np.mean或sum()原生函数,单位就没了 - 序列化保存:用
joblib或pickle可存完整Quantity;用to_json或to_parquet必须先分离.magnitude和.units,否则单位信息全丢
当 pint 不够用:手动处理非标准单位或模糊文本
遇到 "~3.2 Vpp"、"、"2nd harmonic: -45 dBc" 这类含修饰符、缩写、非SI符号的文本,pint 无法直解析。
建议分两步处理:
- 用正则预清洗:提取核心数值和可识别单位部分,例如
re.search(r"([\d.]+)\s*([a-zA-ZμΩ°²³]+)", s) - 对剩余修饰符(如
"RMS","pp")单独建字段,不塞进单位对象里——它们属于测量条件,不是量纲 - 查表映射缩写:
{"dBc": "decibel-centiwatt", "Vpp": "volt_peak_to_peak"},再用ureg.define()注册
单位系统越复杂,越要早做校验:在数据加载后立刻跑一遍 df.applymap(lambda x: hasattr(x, "units")),比后期 debug 强十倍。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










