对比两个DataFrame 按国家正则校验转换邮政编码并解决捕获组报错
报错原因
你遇到的ValueError: pattern contains no capture groups报错,核心原因是pandas的str.extractall()方法要求正则表达式必须包含至少一个带括号的捕获组,你提供的正则表中部分规则(比如拉脱维亚的[L]{1}[V]{1}-{4}、爱尔兰的STRNG_LTN_EXT_255)没有捕获组,其中爱尔兰的规则甚至不是合法正则,批量遍历时碰到这类规则就会触发报错,这也是你单独跑第二层循环没问题、批量跑报错的原因。
另外原代码用双层for循环遍历3.5万条数据效率极低,完全可以用矢量化操作替代。
修改后可直接运行的代码
第一步:导入依赖、读取原始数据
import pandas as pd import re # 读取两个CSV文件,邮编和Contact ID统一读为字符串避免格式丢失 countries_df = pd.read_csv("countries.csv", dtype={"Zip Code": str, "Contact ID": str}) regex_df = pd.read_csv("Regex.csv")
第二步:预处理正则表,解决捕获组缺失问题
def preprocess_regex(reg_str): # 先校验正则合法性 try: re.compile(reg_str) except re.error: return None # 给整个正则外层加全局捕获组,解决无捕获组报错问题 return f"({reg_str})" # 处理正则,过滤无效规则 regex_df["processed_regex"] = regex_df["Regex format"].apply(preprocess_regex) regex_df = regex_df.dropna(subset=["processed_regex"]) # 转成国家-正则映射字典,后续查询效率更高 country_regex_map = dict(zip(regex_df["Country"], regex_df["processed_regex"]))
第三步:批量处理邮编
如果你的国家字段分散在Country of Residence/Mailing Country等多列中,先新增统一的匹配国家字段:
countries_df["matched_country"] = countries_df["Mailing Country (text only)"].fillna( countries_df["Country of Residence"] ).fillna( countries_df["Other Country (text only)"] )
写邮编清洗函数,批量应用:
def clean_zipcode(row): # 如果没有做多列国家合并,把下面的matched_country换成你实际的国家字段名 country = row["matched_country"] raw_zip = str(row["Zip Code"]).strip() # 无对应国家正则的直接返回原始值 if country not in country_regex_map: return raw_zip reg = country_regex_map[country] # 提取符合规则的邮编部分 match_res = re.findall(reg, raw_zip) if match_res: # 取第一个匹配到的有效邮编 return match_res[0] if isinstance(match_res[0], str) else match_res[0][0] # 没匹配到的返回原始值,可按需修改为返回空值标记异常 return raw_zip # 批量处理所有行 countries_df["standard_zipcode"] = countries_df.apply(clean_zipcode, axis=1)
第四步:输出最终结果
# 保留所需字段,Contact ID作为唯一标识 final_df = countries_df[["Contact ID", "Country", "Zip Code", "standard_zipcode"]] # 可按需导出为CSV # final_df.to_csv("standard_zip_result.csv", index=False)
内容的提问来源于stack exchange,提问作者qnt13
相关产品推荐
相关产品推荐

