pandas read_csv 读取数据时如何去除币种标志($、¥、€ 等)
问题背景
在实际数据处理中,我们经常会遇到这样的 CSV 文件:
商品名称,价格,成本
键盘,"$1,299.00","$850.50"
鼠标,"¥399.00","¥220.00"
显示器,"€549.99","€380.00"
直接使用 pd.read_csv() 读取后,价格列会被识别为字符串类型(object),而不是数值类型,无法直接进行求和、均值等数学运算,这是因为数据中混入了币种符号(、、)以及千分位逗号。
本文介绍几种在读取和清洗阶段去除币种标志的常用方法。
方法一:使用 read_csv 的 converters 参数(读取时直接清洗)
converters 参数允许我们对指定列在读取时就应用自定义函数:
import pandas as pd
def clean_currency(x):
"""去除币种符号和千分位逗号,转换为浮点数"""
return float(x.replace('$', '')
.replace('¥', '')
.replace('€', '')
.replace(',', ''))
df = pd.read_csv('data.csv', converters={'价格': clean_currency, '成本': clean_currency})
print(df.dtypes)
输出:
商品名称 object
价格 float64
成本 float64
dtype: object
优点:一步到位,读取完成时数据已是数值类型。
方法二:先读取,后用正则表达式清洗(推荐)
更通用的做法是先正常读取,再用 str.replace() 配合正则表达式批量处理:
import pandas as pd
df = pd.read_csv('data.csv')
for col in ['价格', '成本']:
df[col] = (
df[col]
.str.replace(r'[^\d\.\-]', '', regex=True) # 保留数字、小数点、负号
.astype(float)
)
正则 [^\d\.\-] 的含义是“匹配所有不是数字、小数点、负号的字符”,无论是 、、 还是逗号,都会被一次性清除。
方法三:处理负数的括号表示法
财务数据中常见 ($1,234.56) 表示 -1234.56 的写法,需要额外处理括号:
import pandas as pd
df = pd.read_csv('data.csv')
def parse_currency(series):
series = series.str.replace(r'[$¥€£,]', '', regex=True)
series = series.str.replace(r'\((.*)\)', r'-\1', regex=True) # 括号转负数
return pd.to_numeric(series, errors='coerce') # 无法解析的变为 NaN
df['价格'] = parse_currency(df['价格'])
df['成本'] = parse_currency(df['成本'])
errors='coerce' 可以把空字符串、"N/A" 等脏数据自动转为 NaN,避免程序报错。
注意事项
- 千分位逗号要一并去除:
$1,299.00如果只去掉 而留下逗号,float()转换依然会失败。 - 先查 dtype 再处理:用
df.dtypes确认列类型,如果已经是 float64,说明读取时已被正确解析,无需清洗。 - 空值问题:
str.replace对NaN不生效但也不会报错,转换后用df['价格'].isna().sum()检查缺失情况。 - 编码问题:CSV 中含有 符号,读取时报
UnicodeDecodeError,可尝试指定编码:pd.read_csv('data.csv', encoding='gbk')。 - 读取时指定 dtype=str 更保险:对于脏数据较多的列,可用
dtype={'价格': str}强制按字符串读入,避免 pandas 自动推断出错。
| 方法 | 适用场景 |
|---|---|
converters 参数 |
列数少、规则简单,希望一次读取到位 |
str.replace + astype |
通用场景,代码清晰 |
正则 + pd.to_numeric |
数据脏、含括号负数、含异常值 |
核心思路都是一致的:用字符串替换(或正则)剔除币种符号和千分位符,再转换为数值类型,掌握这几种方法后,无论数据中混的是美元、人民币还是欧元符号,都能轻松完成清洗,为后续的数据分析打下基础。
The End
发布于:2026-10-14,除非注明,否则均为原创文章,转载请注明出处。
