Pandas DataFrame中代码到数值范围块的映射方法求助
刚好做过类似的需求!要把Pandas DataFrame里的代码映射到自定义的数值范围块,还得处理一个代码匹配多个块的情况,咱们一步步来实现:
第一步:先把自定义块规则解析成结构化格式
你给的块是AAA0-9这种「前缀+数字区间」的格式,首先得把它们拆成机器能识别的规则(前缀、起始数字、结束数字),这里用正则表达式就能轻松搞定:
import re import pandas as pd def parse_block_rule(block_str): # 提取前缀(非数字部分)和数字区间 match = re.match(r'([A-Za-z]+)(\d+)-(\d+)', block_str) if match: return { 'prefix': match.group(1), 'start': int(match.group(2)), 'end': int(match.group(3)), 'block_name': block_str } else: raise ValueError(f"这块格式不对哦:{block_str}") # 把你的块列表转换成结构化规则 block_rules = [parse_block_rule(rule) for rule in ['AAA0-9', 'CCC5-9', 'BBB0-5']]
第二步:写个函数判断单个代码匹配哪些块
接下来要做的就是给每个代码做“匹配检查”,拆分它的前缀和数字,然后和所有规则对比,收集所有符合条件的块:
def get_matching_blocks(code, block_rules): # 拆分代码的前缀和数字部分 code_match = re.match(r'([A-Za-z]+)(\d+)', code) if not code_match: return None # 不符合格式的代码直接返回None code_prefix = code_match.group(1) code_num = int(code_match.group(2)) # 遍历所有规则,捞出来所有匹配的块 matching_blocks = [] for rule in block_rules: if (code_prefix == rule['prefix'] and rule['start'] <= code_num <= rule['end']): matching_blocks.append(rule['block_name']) # 多个匹配用逗号分隔,没匹配到就返回None return ','.join(matching_blocks) if matching_blocks else None
第三步:把函数应用到DataFrame上
现在就可以把这个函数套到你的DataFrame代码列上,生成目标的块列了。举个完整的示例:
初始DataFrame(模拟你的数据)
df = pd.DataFrame({ 'code': ['AAA0', 'AAA5', 'BBB3', 'BBB6', 'CCC7', 'DDD2', 'AAA9', 'BBB5'] })
生成目标结果
df['block'] = df['code'].apply(lambda x: get_matching_blocks(x, block_rules))
运行后得到的结果就是你想要的目标DataFrame:
| code | block |
|---|---|
| AAA0 | AAA0-9 |
| AAA5 | AAA0-9 |
| BBB3 | BBB0-5 |
| BBB6 | None |
| CCC7 | CCC5-9 |
| DDD2 | None |
| AAA9 | AAA0-9 |
| BBB5 | BBB0-5 |
如果遇到一个代码匹配多个块的情况(比如你定义了AAA0-5和AAA3-9,那AAA4就会匹配两个块),block列会自动显示AAA0-5,AAA3-9这种逗号分隔的格式,完美覆盖你说的多匹配场景。
小优化建议
- 如果你的代码前缀有大小写混合(比如
aaa0和AAA0),可以在匹配时统一转成大写/小写,比如把code_prefix == rule['prefix']改成code_prefix.upper() == rule['prefix'].upper() - 如果你的数据量特别大,
apply的效率可能不够,可以考虑用向量化的方法(比如pd.Series.str.extract提取前缀和数字,再用np.select批量判断),但上面的方法对于大多数场景已经足够清晰好用了。
内容的提问来源于stack exchange,提问作者shbfy
相关产品推荐
相关产品推荐

