
本文详解为何在 Pandas 中用 str.extract() 提取 GPA 等浮点数值时会丢失小数位,并通过添加原始字符串前缀 r 修复正则转义问题,确保 2.4、3.654、3.87 等完整数值被准确捕获和转换。
本文详解为何在 pandas 中用 `str.extract()` 提取 gpa 等浮点数值时会丢失小数位,并通过添加原始字符串前缀 `r` 修复正则转义问题,确保 `2.4`、`3.654`、`3.87` 等完整数值被准确捕获和转换。
在数据清洗过程中,常需从含噪声的字符串列(如 '3.654'、'3.79 btch'、'Personal '、'Unknown')中提取有效数值。上述代码看似合理:先转为字符串,再用正则匹配数字,最后转为数值类型。但结果却只保留整数部分(如 3.0、2.0、4.0),根本原因是正则表达式中的反斜杠 \d 和 \. 在普通字符串中未被正确解析。
Python 普通字符串会将 \d 视为转义序列(实际等价于 ASCII 字符 \x0d,即回车符),而非正则意义上的“数字字符类”;同理,\. 本意是匹配字面量点号,但在非原始字符串中可能被误解释或失效。这导致正则模式 (\d*\.\d+|\d+) 实际未能按预期工作——尤其 \., \d 失效后,匹配逻辑崩溃,仅偶然捕获到孤立的整数部分(如 '3' 或 '4'),最终 pd.to_numeric() 将其统一转为 3.0、4.0 等浮点整数。
✅ 正确做法是使用原始字符串(raw string),在正则前加 r 前缀,让反斜杠不被 Python 字符串解析器预处理,而是直接传递给正则引擎:
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+)' 含两部分:
-
\d*\.\d+:匹配零个或多个数字 + 字面量点号 + 一个或多个数字 → 覆盖'.5'、'0.123'、'3.654'; -
\d+:匹配一个或多个数字 → 覆盖'3'、'4'等整数。
⚠️ 注意事项:
-
expand=False返回 Series(推荐),避免生成多余 DataFrame; -
errors='coerce'将无法转换的值设为NaN,安全兜底; - 若存在
'2.'或'.7'类边缘格式,可增强正则为r'(\d+\.\d*|\.\d+|\d+)'; - 提取前建议检查空值/空字符串:
food['GPA'] = food['GPA'].replace('', np.nan)。
执行后,food['GPA'].unique() 将如实返回 [2.4, 3.654, 3.3, 3.2, ..., 3.882] 等原始精度数值,彻底解决小数丢失问题。











