
本文讲解为何在 Pandas 中用 str.extract() 提取 GPA 等浮点数值时会丢失小数位,并通过添加原始字符串前缀 r 和优化正则模式,确保 2.4、3.654、2.25 等精度完整保留。
本文讲解为何在 pandas 中用 `str.extract()` 提取 gpa 等浮点数值时会丢失小数位,并通过添加原始字符串前缀 `r` 和优化正则模式,确保 `2.4`、`3.654`、`2.25` 等精度完整保留。
在数据清洗过程中,常遇到类似 GPA 字段包含杂乱字符串(如 '3.79 btch'、'Personal '、'Unknown')的情况。为统一转为数值类型,典型做法是先转为字符串,再用正则提取数字部分,最后转换为数值。但若忽略原始字符串(raw string) 的必要性,正则中的反斜杠 \d 会被 Python 解释器误处理,导致匹配逻辑失效——这正是小数丢失的根本原因。
例如,未加 r 前缀的 '\d*\.\d+|\d+' 在 Python 字符串中,\. 会被解释为字面量 .(而非“匹配小数点”),而 \d 可能被误识别为非法转义(尤其在旧版本中),最终仅匹配到孤立的整数部分(如 '4'、'3'),造成 3.654 被截断为 3,2.25 变成 2,最终 unique() 仅显示 [2., 3., 4.]。
✅ 正确写法必须使用原始字符串前缀 r,确保正则元字符按预期工作:
food['GPA'] = food['GPA'].astype(str).str.extract(r'(\d+\.\d+|\d+)', expand=False) food['GPA'] = pd.to_numeric(food['GPA'], errors='coerce')
? 正则说明:
r'(\d+\.\d+|\d+)'—— 优先匹配带小数点的数字(如3.654), fallback 匹配纯整数(如4);- 使用
\d+(而非\d*)避免匹配空字符串或孤立小数点(如'.5');expand=False返回 Series,便于链式赋值;errors='coerce'将无法转换的值设为NaN,安全兜底。
? 额外建议:
- 若源数据含前导/尾随空格(如
'3.8 ',' 2.6'),可先.str.strip(); - 对
'3.79 btch'类型,当前正则已能捕获3.79;但若存在'GPA:3.83',可升级为r'(\d+\.\d+|\d+)(?=\D|$)'实现更健壮的边界匹配; - 执行后建议验证:
food['GPA'].apply(lambda x: len(str(x).split('.')[-1]) if '.' in str(x) else 0).max()检查最大保留小数位数。
最终,food['GPA'].unique() 将如实返回 [2.4, 3.654, 3.3, ..., 3.882] 等原始精度数值,彻底解决小数截断问题。

















