Pandas正则匹配异常:提取带单位数值触发IndexError索引错误
解决提取数字加单位时的IndexError问题
错误原因分析
你遇到的IndexError: list index out of range,根源在两个细节上:
names函数的正则匹配不严谨:第二个正则((\d*)l)里的\d*允许匹配0个数字,这意味着如果文本里出现单独的l/L(比如单词末尾的L、无数字的L),这个正则会错误地匹配到它,返回类似L的空数字字符串给measure函数。measure函数缺少空值防护:当传入的val不含任何数字时,re.findall会返回空列表,此时强行取[0]自然触发索引越界错误。
修复方案
我们从两个层面修正代码,同时优化整体逻辑:
1. 修正names函数,确保只匹配「有效数字+单位」组合
把允许0个数字的\d*改成要求至少一个数字的\d+,合并重复的正则搜索逻辑,同时用忽略大小写的规则简化单位匹配:
import re import pandas as pd def names(header): # 匹配ml相关单位(支持整数/小数、可选空格、大小写) ml_match = re.search(r'(\d+\.?\d*\s*ml)', header, flags=re.IGNORECASE) if ml_match: return ml_match.group() # 匹配l/L/lt/Lt相关单位(规则同上) l_match = re.search(r'(\d+\.?\d*\s*(?:l|lt))', header, flags=re.IGNORECASE) if l_match: return l_match.group() # 无匹配返回None return None
这里的正则优化点:
\d+\.?\d*:兼容整数(如12)和小数(如12.5)\s*:允许数字和单位之间有0个或多个空格flags=re.IGNORECASE:不用单独枚举ML、mL等大小写变体(?:l|lt):非捕获组,统一匹配l/L/lt/Lt单位
2. 给measure函数增加空值判断,避免索引越界
在提取数字前先检查有效性,同时简化单位判断逻辑:
def measure(val): if not val: return None # 提取数字部分 num_match = re.search(r'(\d+\.?\d*)', val) if not num_match: return None num = float(num_match.group()) # 判断单位并转换 if re.search(r'ml', val, flags=re.IGNORECASE): return num elif re.search(r'(l|lt)', val, flags=re.IGNORECASE): return num * 1000 return None
3. 修正DataFrame拼接逻辑
原代码中dropna()会导致行数不匹配,直接对apply(names)的结果调用measure即可,让measure处理None的情况:
# 构造测试DataFrame df = pd.DataFrame({ 'text': [ '1234567-CAR WA GK5 9x78x90 12L', '3456789 TOP-L BD3 195x169x62 TopL' ] }) # 生成结果 df_result = pd.concat([ df['text'], df['text'].apply(names).rename('text extract'), df['text'].apply(names).apply(measure).rename('Return') ], axis=1) # 把None替换为预期的'-' df_result = df_result.fillna('-')
最终输出结果
运行修正后的代码,得到完全符合预期的输出:
| text | text extract | Return |
|---|---|---|
| 1234567-CAR WA GK5 9x78x90 12L | 12L | 12000 |
| 3456789 TOP-L BD3 195x169x62 TopL | - | - |
内容的提问来源于stack exchange,提问作者sanjana jha
相关产品推荐
相关产品推荐

