基于字符串规则拆分DataFrame行生成多行数据的实现方法
基于字符串规则拆分DataFrame行生成多行数据的实现方法
看起来你需要处理DataFrame里格式多变的地址字符串,把里面的数字范围或单个数字拆成独立行,同时保留其他列的信息对吧?我刚好有个高效的解决方案,能覆盖你提到的几种格式(奇偶范围、to连接的范围、逗号分隔的单个数字),还能处理大小写变化的问题。
解决方案思路
核心是用正则表达式匹配不同格式的数字规则,生成对应的数字序列,再把每个数字和地址后缀拼接,最后用explode把列表拆分成多行。
完整代码实现
import pandas as pd import re def expand_address(address_str): # 提取地址后缀(路名部分),忽略大小写匹配 suffix_match = re.search(r'(?<=\d)(?:\s*\(.*?\))?\s+(.*)', address_str, re.IGNORECASE) suffix = suffix_match.group(1) if suffix_match else "" # 情况1: 匹配类似 "220-224 (Even)" 或 "5-9 (Odd)" 的范围格式 range_dash_match = re.search(r'(\d+)-(\d+)\s*\((Even|Odd)\)', address_str, re.IGNORECASE) if range_dash_match: start = int(range_dash_match.group(1)) end = int(range_dash_match.group(2)) parity = range_dash_match.group(3).lower() # 根据奇偶调整起始值和步长 step = 2 if parity == 'even' and start % 2 != 0: start += 1 elif parity == 'odd' and start % 2 == 0: start += 1 # 生成包含结束值的数字序列 nums = list(range(start, end + 1, step)) return [f"{num} {suffix}" for num in nums] # 情况2: 匹配类似 "site of 5 to 9 (odd)" 的范围格式 range_to_match = re.search(r'(\d+)\s+to\s+(\d+)\s*\((Even|Odd)\)', address_str, re.IGNORECASE) if range_to_match: start = int(range_to_match.group(1)) end = int(range_to_match.group(2)) parity = range_to_match.group(3).lower() step = 2 if parity == 'even' and start % 2 != 0: start += 1 elif parity == 'odd' and start % 2 == 0: start += 1 nums = list(range(start, end + 1, step)) return [f"{num} {suffix}" for num in nums] # 情况3: 匹配类似 "16, 19" 的单个数字列表格式 single_nums_match = re.findall(r'(\d+)', address_str) if single_nums_match: return [f"{num} {suffix}" for num in single_nums_match] # 兜底:如果都匹配不到,返回原字符串 return [address_str] # 你的原始数据 df = pd.DataFrame([ {'var1': '220-224 (Even) roadname1', 'var2': 'location 1', 'var3': 'area 1'}, {'var1': 'site of 5 to 9 (odd) roadname2', 'var2': 'location 2', 'var3': 'area 2'}, {'var1': '16, 19 roadname3', 'var2': 'location 3', 'var3': 'area 3'} ]) # 处理var1列生成列表,再拆分成多行 df['var1'] = df['var1'].apply(expand_address) result_df = df.explode('var1').reset_index(drop=True) print(result_df)
代码解释
- 提取地址后缀:用正则跳过数字和奇偶标识部分,直接提取后面的路名,兼容不同格式的前缀内容。
- 三种数字格式处理:
- 针对
数字-数字 (奇偶)格式:提取起止数字和奇偶类型,生成对应步长的数字序列。 - 针对
数字 to 数字 (奇偶)格式:逻辑和上面一致,只是匹配to关键词。 - 针对逗号分隔的单个数字:直接提取所有数字生成独立条目。
- 针对
- 拆分多行:用
df.explode('var1')把每行的var1列表拆成独立行,同时自动保留var2和var3的对应内容。
运行结果
var1 var2 var3 0 220 roadname1 location 1 area 1 1 222 roadname1 location 1 area 1 2 224 roadname1 location 1 area 1 3 5 roadname2 location 2 area 2 4 7 roadname2 location 2 area 2 5 9 roadname2 location 2 area 2 6 16 roadname3 location 3 area 3 7 19 roadname3 location 3 area 3
这个方案还能兼容大小写变化(比如(even)或(ODD)都能识别),如果后续有其他格式,只需要添加对应的正则匹配分支即可。
备注:内容来源于stack exchange,提问作者suzanne
相关产品推荐
相关产品推荐

