Pandas Dataframe:基于其他列条件为新列赋值求助
解决DataFrame基于多字段匹配赋值的问题
问题分析
你原来的嵌套循环存在三个核心问题:
- 效率极低:嵌套循环时间复杂度为O(n*m),面对大型CSV会导致程序运行极慢甚至内存溢出
- 逻辑错误:判断条件
grid['91-120'][j] in df2['Grid'][i]完全不符合需求——你需要判断df2的Grid值属于哪个区间,而非判断折扣值是否存在于Grid中;同时未匹配Entity字段,导致跨Entity的错误匹配 - 值覆盖问题:循环中每次匹配都会覆盖之前的赋值,最终可能只剩最后一次循环的结果(比如全0)
高效解决方案(适合大型数据集)
我们可以通过构建映射表+合并匹配的方式实现,完全避免循环:
1. 重构df1为匹配用的映射表
假设df1是宽表结构(每行对应一个Entity,每列对应一个Grid区间,值为对应折扣),先将其转换为窄表,方便后续匹配:
import pandas as pd # 将df1转为(Entity, Grid区间) -> 折扣的映射格式 mapping_df = df1.melt(id_vars='Entity', var_name='Grid_Interval', value_name='Discount%')
2. 标记df2中Grid值所属的区间
根据你的规则,先定义区间范围,给df2新增列标记其Grid所属的区间:
# 定义区间规则(right=False表示左闭右开,比如61-90包含61,不包含91) bins = [0, 60, 90, 120, float('inf')] labels = ['0-60', '61-90', '91-120', '120+'] # 给df2添加所属区间列 df2['Grid_Interval'] = pd.cut(df2['Grid'], bins=bins, labels=labels, right=False)
如果df2的Grid列已经是区间字符串(比如"91-120"),则跳过此步骤,直接使用原Grid列作为匹配字段。
3. 基于Entity和区间匹配赋值
用merge方法将两个表按Entity和Grid_Interval合并,自动填充折扣值:
# 合并表,匹配对应折扣 df2 = df2.merge(mapping_df, on=['Entity', 'Grid_Interval'], how='left') # 对匹配不到的情况填充默认值(比如0) df2['Discount%'] = df2['Discount%'].fillna(0) # 若不需要Grid_Interval列,可删除 df2 = df2.drop(columns='Grid_Interval')
示例验证
假设df1结构:
| Entity | 0-60 | 61-90 | 91-120 |
|---|---|---|---|
| A | 0 | 5 | 20 |
| B | 0 | 3 | 15 |
df2初始结构:
| Entity | Grid |
|---|---|
| A | 75 |
| A | 100 |
| B | 50 |
| B | 95 |
处理后df2结果:
| Entity | Grid | Discount% |
|---|---|---|
| A | 75 | 5 |
| A | 100 | 20 |
| B | 50 | 0 |
| B | 95 | 15 |
内容的提问来源于stack exchange,提问作者saq
相关产品推荐
相关产品推荐

