通过从数据帧的多个列中进行条件选择进行向量算术

时间:2019-08-01 14:59:14

标签: python pandas dataframe

我正在尝试在数据框中的不同单元之间进行算术运算,无法弄清楚如何对每个组进行运算。我正在尝试找出每座建筑物的基准建筑物(在此示例中,energy_use是基准情况)与upgrade_name == b之间的差异。我有任意数量的building_id和任意数量的upgrade_name

我可以成功完成一个building_id的操作。现在,我需要将其扩展到完整的数据集并陷入困境。我将拥有成千上万的建筑物,每个建筑物都有数十个升级。

这个问题Iterating within groups in Pandas的答案可能是相关的,但是我不确定如何将其应用于我的问题。

我有一个这样的数据框:

df = pd.DataFrame({'building_id': [1,2,1,2,1], 'upgrade_name': ['a', 'a', 'b', 'b', 'c'], 'energy_use': [100.4, 150.8, 145.1, 136.7, 120.3]})
In [4]: df
Out[4]:
   building_id upgrade_name  energy_use
0            1            a       100.4
1            2            a       150.8
2            1            b       145.1
3            2            b       136.7
4            1            c       120.3

对于一个building_id,我有以下代码:

upgrades = df.loc[df.building_id == 1, ['upgrade_name', 'energy_use']]
starting_point = upgrades.loc[upgrades.upgrade_name == 'b', 'energy_use']
upgrades['diff'] = upgrades.energy_use - starting_point.values[0]
In [8]: upgrades
Out[8]:
  upgrade_name  energy_use  diff
0            a       100.4 -44.7
2            b       145.1   0.0
4            c       120.3 -24.8

如何为任意数量的building_id而不是我的硬编码building_id == 1编写此代码? 理想的解决方案如下所示(基线差异是0还是NaN都没有关系):

In [17]: df
Out[17]:
   building_id upgrade_name  energy_use  ideal
0            1            a       100.4  -44.7
1            2            a       150.8   14.1
2            1            b       145.1    0.0
3            2            b       136.7    0.0
4            1            c       120.3  -24.8

2 个答案:

答案 0 :(得分:1)

感谢您分享示例数据!使事情变得容易得多。

我建议分两个部分解决这个问题:
1.从数据框中制作一个字典,其中包含每个建筑物的基准能耗
2.将lambda函数应用于您的数据框,以从与该建筑物关联的基准值中减去每个能耗值。

# set index to building_id, turn into dictionary, filter out energy use
building_baseline = df[df['upgrade_name'] == 'b'].set_index('building_id').to_dict()['energy_use']

# apply lambda to dataframe, use axis=1 to access rows
df['diff'] = df.apply(lambda row: row['energy_use'] - building_baseline[row['building_id']])

您还可以编写一个函数来执行此操作。您也不一定需要字典,它只是使事情变得简单。如果您对这些替代解决方案感到好奇,请告诉我,我可以为您添加它们。

答案 1 :(得分:1)

定义计算能源使用差异的函数(用于 当前建筑物的一组行),如下所示:

def euDiff(grp):
    euBase = grp[grp.upgrade_name == 'b'].energy_use.values[0]
    return grp.energy_use - euBase

然后计算差异(针对所有建筑物),并将其应用于每个组:

df['ideal'] = df.groupby('building_id').apply(euDiff)\
    .reset_index(level=0, drop=True)

结果与您预期的一样。