Pandas拆分DataFrame字符串范围数据时触发ValueError求助
报错原因
- 核心问题1:自定义
split函数逻辑冗余且未做脏数据处理。原函数对字符串按-分割后又对每个分割结果重复按-分割属于无效逻辑,且没有对HouseNum字段做去空格、空值过滤,一旦单元格存在纯空格内容、多余横杠、空值,int()转换就会拿到纯空格/空字符串触发报错。 - 核心问题2:行展开代码引用了不存在的列。你的拆分结果存在
HouseNum列,代码里写的是不存在的Options列,运行到该行会触发属性错误。 - 鲁棒性问题:直接用
HouseNum字符串长度切片取街道名的逻辑容错性差,一旦门牌号前后带空格,切出来的街道名开头会残留多余空格。
修复方案
先做字段清洗,再优化拆分逻辑,用pandas原生explode方法做行展开,代码可读性和兼容性更好,适配pandas 1.3及以上版本:
import pandas as pd def split_house_num(s): # 基础清洗:去前后空格、移除横杠两侧的多余空格 s = s.strip().replace(" ", "") # 空值直接返回空列表 if not s: return [] # 按横杠分割,过滤空片段,兼容多横杠的异常输入 parts = [p for p in s.split("-") if p] if len(parts) == 1: # 单个门牌号直接返回 return [int(parts[0])] # 范围值取首尾生成连续序列 start = int(parts[0]) end = int(parts[-1]) return list(range(start, end + 1)) xlsx = 'drive/MyDrive/Parcels.xlsx' parcels = pd.read_excel(xlsx, usecols=['parcel_id','prop_locat','ZipCode','HouseNum']) # 统一转字符串并清洗前后空格 parcels['HouseNum'] = parcels['HouseNum'].astype(str).str.strip() # 优化街道提取逻辑:按第一个空格拆分,前面为门牌号、后面为街道,避免长度计算误差 parcels[['_', 'address']] = parcels['prop_locat'].str.split(n=1, expand=True) # 拆分门牌号范围 parcels['HouseNum'] = parcels['HouseNum'].apply(split_house_num) # 展开为多行,丢弃拆分失败的空行 parcels = parcels.explode('HouseNum', ignore_index=True) # 拼接生成完整地址 parcels['full_address'] = parcels['HouseNum'].astype(str) + " " + parcels['address'] # 筛选输出需要的列 parcels = parcels[['parcel_id', 'ZipCode', 'HouseNum', 'address', 'full_address']] print(parcels)
运行效果
用你提供的样例数据集运行后,输出结果符合预期:
| parcel_id | ZipCode | HouseNum | address | full_address |
|---|---|---|---|---|
| xxxxxxxxxxxxxx | xxxxx | 1234 | W 500 S | 1234 W 500 S |
| xxxxxxxxxxxxxx | xxxxx | 123 | W 700 S | 123 W 700 S |
| xxxxxxxxxxxxxx | xxxxx | 124 | W 700 S | 124 W 700 S |
| ... | ... | ... | ... | ... |
| xxxxxxxxxxxxxx | xxxxx | 130 | W 700 S | 130 W 700 S |
兼容特殊值的优化
如果数据里存在带字母的非纯数字门牌号(比如123A),可以给拆分函数加异常捕获,避免中断运行,同时保留异常值方便后续排查脏数据:
def split_house_num(s): s = s.strip().replace(" ", "") if not s: return [] parts = [p for p in s.split("-") if p] try: if len(parts) == 1: return [parts[0]] start = int(parts[0]) end = int(parts[-1]) return list(range(start, end + 1)) except: # 转换失败直接返回原始值 return [s]
内容的提问来源于stack exchange,提问作者rweber
相关产品推荐
相关产品推荐

