
本文详解如何安全清洗并转换含货币符号、逗号和小数的字符串价格列(如 "$4,000.00")为 int 类型,解决 .str 访问器报错及正则转义警告问题。
本文详解如何安全清洗并转换含货币符号、逗号和小数的字符串价格列(如 "$4,000.00")为 int 类型,解决 `.str` 访问器报错及正则转义警告问题。
在使用 pandas 读取 CSV 文件时,带有美元符号、千位逗号和小数部分的价格字段(如 "$4,000.00")默认会被识别为 object 类型(即字符串),直接调用 .str.replace() 会触发 AttributeError: Can only use .str accessor with string values! 错误——这通常意味着该列中存在非字符串值(如 NaN、数字或空值)。此外,原始代码中的正则表达式 [\$\,]|\.\d* 存在两个关键问题:一是未使用原始字符串(r'')导致 \$$ 被解释为无效转义;二是 str.replace() 默认不启用正则(需显式设置 regex=True)。
以下是推荐的稳健转换流程,分三步完成:
✅ 步骤 1:确保列值为字符串并安全清洗
先统一转为字符串(避免 NaN 导致 .str 失效),再用 regex=True 清洗符号与小数部分:
# 确保 Price 列所有值为字符串(自动将 NaN 转为 'nan',后续可处理) cars_sales["Price"] = cars_sales["Price"].astype(str) # 使用原始字符串 + regex=True 清除 $、, 和小数点后所有数字(包括 .00) cars_sales["Price"] = cars_sales["Price"].str.replace(r'[\$\,]|\.(\d+)', '', regex=True)
? 注:r'[$\,]|\.(\d+)' 中 r'' 避免转义警告;|\.(\d+) 比 |\.\d* 更精准匹配小数部分(括号非捕获也可,但写法更清晰)。
✅ 步骤 2:转换为数值并处理异常
使用 pd.to_numeric(..., errors='coerce') 将清洗后的字符串转为浮点数,无法解析的值(如纯 'nan')自动转为 NaN:
cars_sales["Price"] = pd.to_numeric(cars_sales["Price"], errors='coerce')
✅ 步骤 3:填充缺失值并转为整数
对 NaN 做合理填充(如填 0 或 mean()),再转 int(注意:astype(int) 不接受 NaN,必须先填充):
# 方案 A:填 0(适用于无价格视为免费的场景) cars_sales["Price"] = cars_sales["Price"].fillna(0).astype(int) # 方案 B:填均值(更符合统计建模需求) # price_mean = cars_sales["Price"].mean() # cars_sales["Price"] = cars_sales["Price"].fillna(round(price_mean)).astype(int)
? 完整可运行示例
import pandas as pd
# 模拟原始数据(含可能的 NaN)
data = {
"Make": ["Toyota", "Honda", "Ford", "BMW"],
"Colour": ["White", "Black", "Blue", "Red"],
"Odometer (KM)": [150043, 86000, 123000, 95000],
"Doors": [4, 4, 2, 4],
"Price": ["$4,000.00", "$5,500.00", "$7,000.00", None] # 注意最后一个为 None → NaN
}
cars_sales = pd.DataFrame(data)
# 执行三步转换
cars_sales["Price"] = cars_sales["Price"].astype(str)
cars_sales["Price"] = cars_sales["Price"].str.replace(r'[\$\,]|\.(\d+)', '', regex=True)
cars_sales["Price"] = pd.to_numeric(cars_sales["Price"], errors='coerce')
cars_sales["Price"] = cars_sales["Price"].fillna(0).astype(int)
print(cars_sales.dtypes)
print(cars_sales)
✅ 输出:
Make object
Colour object
Odometer (KM) int64
Doors int64
Price int64
dtype: object
Make Colour Odometer (KM) Doors Price
0 Toyota White 150043 4 4000
1 Honda Black 86000 4 5500
2 Ford Blue 123000 2 7000
3 BMW Red 95000 4 0
⚠️ 关键注意事项
- 永远先检查缺失值:cars_sales["Price"].isna().sum() 可快速定位 NaN;
- 避免直接 astype(int):NaN 会导致 ValueError,务必配合 fillna() 或 dropna();
- 正则务必加 r'' 前缀:否则 \$$、\, 触发 SyntaxWarning;
- errors='coerce' 是安全兜底:比 errors='raise' 更适合真实数据清洗;
- 如需保留小数(如精确到美分),最后用 astype(float) 或 round(0) 后转 int。
遵循此流程,即可稳定、可复现地将各类格式化价格字符串转化为整型数值,为后续分析与建模奠定可靠基础。











