基于两个DataFrame按范围求和时遇错误:仅可比较标签一致的Series对象
问题:按区间计算对应列的求和值
原始数据
表t1
| id | mins | maxs | |
|---|---|---|---|
| 0 | 43852 | 11 | 11 |
| 1 | 63087 | 14 | 15 |
| 2 | 63106 | 14 | 15 |
| 3 | 63155 | 14 | 15 |
表t2
| idx | cons | |
|---|---|---|
| 0 | 1 | 1.00 |
| 1 | 2 | 0.95 |
| 2 | 3 | 0.90 |
| 3 | 4 | 0.85 |
| 4 | 5 | 0.80 |
| 5 | 6 | 0.70 |
| 6 | 7 | 0.70 |
| 7 | 8 | 0.65 |
| 8 | 9 | 0.60 |
| 9 | 10 | 0.55 |
| 10 | 11 | 0.50 |
| 11 | 12 | 0.45 |
| 12 | 13 | 0.40 |
| 13 | 14 | 0.35 |
| 14 | 15 | 0.35 |
| 15 | 16 | 0.30 |
需求
为t1中的每个id,计算t2内idx处于对应mins至maxs区间的cons列数值之和。
报错信息
运行代码时出现如下错误:
error: can only compare identically-labeled Series objects
运行的代码
t2.loc[(t2['idx']>= t1['mins']) & (t2['idx']<=t1['maxs']), 'cons'].sum()
预期结果
| id | mins | maxs | result | |
|---|---|---|---|---|
| 0 | 43852 | 11 | 11 | 0.50 |
| 1 | 63087 | 14 | 15 | 0.70 |
| 2 | 63106 | 14 | 15 | 0.70 |
| 3 | 63155 | 14 | 15 | 0.70 |
解决方案
原因分析
原代码报错是因为t2['idx']是一维Series,而t1['mins']/t1['maxs']是长度为4的Series,两者标签不匹配,无法直接逐元素比较。需要为t1的每一行单独计算对应区间的求和。
方法1:使用apply逐行计算
import pandas as pd # 构造示例数据 t1 = pd.DataFrame({ 'id': [43852, 63087, 63106, 63155], 'mins': [11,14,14,14], 'maxs': [11,15,15,15] }) t2 = pd.DataFrame({ 'idx': range(1,17), 'cons': [1.00,0.95,0.90,0.85,0.80,0.70,0.70,0.65,0.60,0.55,0.50,0.45,0.40,0.35,0.35,0.30] }) # 定义区间求和函数 def calculate_sum(row): mask = (t2['idx'] >= row['mins']) & (t2['idx'] <= row['maxs']) return t2.loc[mask, 'cons'].sum() # 应用到t1每一行 t1['result'] = t1.apply(calculate_sum, axis=1) print(t1)
方法2:广播矩阵运算(适合大数据量)
如果数据量较大,apply效率偏低,可通过广播生成布尔矩阵批量计算:
# 生成布尔矩阵:t1每行对应t2所有idx是否在区间内 mask = (t2['idx'].values >= t1['mins'].values[:, None]) & (t2['idx'].values <= t1['maxs'].values[:, None]) # 矩阵乘法快速求和 t1['result'] = mask @ t2['cons'].values print(t1)
两种方法均可得到预期结果。
内容的提问来源于stack exchange,提问作者biyazelnut
相关产品推荐
相关产品推荐

