Python实现仅将指定时间单位前的整数转为对应文本并修复pandas报错
问题根因拆解
1. 同值数字错误全局替换的原因
原代码的替换逻辑存在本质缺陷:
- 先用正则捕获到“位于单位前的目标数字”后,直接使用无位置锁定的全局
re.sub替换,只要文本中出现相同数字字符串,就会被全部替换,完全不关心该数字是否在指定单位前方 - 举例:捕获到“45 hours”前的45后,执行
re.sub("45", "forty-five ", text),会把句首不跟单位的45也一并替换
2. pandas处理时报UnboundLocalError的原因
原函数的变量逻辑存在漏洞:
- 当输入文本中没有任何匹配的数字片段时,
re.findall返回空列表,循环体完全不执行,变量clean从未被定义,后续执行return clean时就会触发未定义变量报错 - 你测试用的第一条文本"I am writing some very basic english sentences"本身没有任何数字,天然会触发这个报错
- 额外附带小bug:定义原始数据时变量名为
text,创建DataFrame时却传入了未定义的raw_docs,会直接触发NameError
修正方案
直接重构替换逻辑,用正则的回调匹配机制锁定替换范围,从根源上避免全局替换的问题:
- 正则添加单词边界,避免误匹配单词内部的数字串
- 使用
re.sub的回调函数模式,仅替换匹配位置的数字,不影响其他位置的同值数字 - 无需手动维护中间替换变量,无匹配场景下
re.sub会原样返回原文本,天然消除未定义变量报错
import pandas as pd from num2words import num2words import re # 原始测试数据 raw_text = [[1, "I am writing some very basic english sentences"], [2, " i am 45 old and worked 3 times this week for 45 hours " ], [3, " i am 75 old and worked 6 times this week for 45 hours "]] Data = pd.DataFrame(raw_text, columns=["index", "text"]) def remove_numbers(text): # 正则结构:1组捕获数字,2组捕获数字和单位之间的空白,后接目标单位(零宽环视,不消耗单位字符) pattern = re.compile(r'\b(\d+)(\s*)(?=hour|day|days|hours|hrs|hr|minutes|min|time|times)\b') # 回调函数:将数字转为英文,保留原有空白 def match_to_words(match): num_part = match.group(1) space_part = match.group(2) return f"{num2words(num_part)}{space_part}" # 直接执行替换,无匹配时原样返回输入文本 return pattern.sub(match_to_words, text) # 直接对Series执行map即可,不需要额外套pd.DataFrame Data['text'] = Data['text'].map(remove_numbers)
效果验证
- 对输入"I am 45, I came here 4 times and I have been waiting for 45 hours.",输出为"I am 45, I came here four times and I have been waiting for forty-five hours.",完全符合预期:句首不跟单位的45保持不变,位于times、hours前的数字正确转成英文文本
- 全DataFrame批量处理时不会触发变量未定义报错,无数字的纯文本行原样保留
内容的提问来源于stack exchange,提问作者Maestra
相关产品推荐
相关产品推荐

