Pandas使用replace或regex清洗DataFrame文本未达预期怎么办?
问题根因
之前的清洗代码从逻辑到索引写法都存在硬伤,才会得到粘连的错误结果:
- 列访问方式错误:示例中的DataFrame仅存在名为
DC的单列,不存在df['DC']['Double_Chance']这种嵌套索引结构,正常运行会直接触发KeyError - 字符删除顺序完全错位:第一步正则
r'([^\d\.\n])'会把所有非数字、非小数点、非换行的字符全部删掉,原本夹杂在说明文字里的零散数字(比如“1 OR X”中的1、“X OR 2”中的2)不会被过滤,反而会和相邻位置的赔率数字直接拼接成无意义的长字符串;后续单独替换1\n、2\n的操作因为匹配不到已经粘连的字符,完全起不到过滤作用,最终就会出现2.50\n1.111.20这类拼接错误。 - 清洗思路走偏:目标是提取固定格式的赔率值,而非无差别删除不需要的文本,盲删很容易把需要保留的数字和需要过滤的零散数字混在一起。
可直接落地的清洗方案
核心思路:直接锚定赔率的固定格式(整数部分+小数点+两位小数),从原始文本中把所有符合格式的片段提取出来,用换行符拼接,同时兼容带HTML标签的原始数据格式。
代码实现
import pandas as pd import re # 两种场景的测试数据:带HTML标签、纯文本 df_html = pd.DataFrame({'DC': ['DOUBLE CHANCE\n1 OR X\n<strong>2.50</strong>\nX OR 2\n<strong>1.12</strong>\n1 OR 2\n<strong>1.20</strong>']}) df_plain = pd.DataFrame({'DC': ['DOUBLE CHANCE\n1 OR X\n2.50\nX OR 2\n1.12\n1 OR 2\n1.20']}) # 清洗逻辑:匹配所有两位小数格式的赔率,用换行拼接 def clean_text(raw_text): odds = re.findall(r'\d+\.\d{2}', raw_text) return '\n'.join(odds) # 应用到DataFrame列 df_html['cleaned'] = df_html['DC'].apply(clean_text) df_plain['cleaned'] = df_plain['DC'].apply(clean_text)
纯str.replace+regex实现版本
如果要求必须用pandas的字符串正则替换方法完成,可直接写为:
# 第一步:把所有非数字/小数点的字符替换为分隔符,第二步把分隔符统一替换为换行,最后去掉首尾空行 df_html['cleaned'] = df_html['DC'].str.replace(r'[^\d.]+', ' ', regex=True).str.strip().str.replace(r'\s+', '\n', regex=True)
两种实现的输出结果完全一致,均为
2.50\n1.12\n1.20,和预期匹配。因为匹配过程锚定了完整的赔率格式,零散出现在说明文字里的单个数字因为凑不成“x.xx”的结构,不会被纳入结果,从根源上避免了字符粘连的问题。
内容的提问来源于stack exchange,提问作者stephen.m
相关产品推荐
相关产品推荐

