首页 > 解决方案 > Pandas:交换一个数据框中的特定列值并计算其加权平均值

问题描述

存在以下数据框:

弹出0 流行音乐1 城市0 城市1
2019 20 40 马里布 纽约市
2018 8 60 悉尼 都柏林
2018 36 23 纽约市 马里布
2020 17 44 马里布 纽约市
2019 5 55 悉尼 都柏林

我想将每个城市对的人口加权平均值计算为一个新列。例如,w_meanMalibu / NYC = (23+20+17)/(36+40+44) = 0.5。

以下是所需的输出:

弹出0 流行音乐1 城市0 城市1 w_mean
2018 23 36 马里布 纽约市 0.5
2019 20 40 马里布 纽约市 0.5
2020 17 44 马里布 纽约市 0.5
2018 8 60 悉尼 都柏林 0.113
2019 5 55 悉尼 都柏林 0.113

我已经按列对数据框进行了排序,但是我在将第三行从 NYC/Malibu 交换到 Malibu/NYC 时遇到了问题。除此之外,我只能计算w_mean每一行,但不能计算每一组。我试过groupby().mean()但没有得到任何有用的输出。

当前代码:

import pandas as pd

data = pd.DataFrame({'year': ["2019", "2018", "2018", "2020", "2019"], 'pop0': [20,8,36,17,5], 'pop1': [40,60,23,44,55], 'city0': ['Malibu','Sydney','NYC','Malibu','Sydney'], 'city1': ['NYC','Dublin','Malibu','NYC','Dublin']})

new = data.sort_values(by=['city0', 'city1'])
new['w_mean'] = new.apply(lambda row: row.pop0 / row.pop1, axis=1)
print(new)

标签: pythonpandasdataframesortingsplit-apply-combine

解决方案


您可以做的是创建一个创建元组(city, population),将两个元组连续放入一个列表中,然后对其进行排序。通过对所有行执行此操作,您可以提取新的城市和人口(按城市字母顺序排序)。这可以按如下方式完成:

cities = [sorted([(e[0], e[1]), (e[2], e[3])]) for e in data[['city0','pop0','city1','pop1']].values]
data[['city0', 'pop0']] = [e[0] for e in cities]
data[['city1', 'pop1']] = [e[1] for e in cities]

结果数据框:

    year  pop0  pop1  city0    city1
0   2019    20    40  Malibu     NYC
1   2018    60     8  Dublin  Sydney
2   2018    23    36  Malibu     NYC
3   2020    17    44  Malibu     NYC
4   2019    55     5  Dublin  Sydney

现在,mean_w可以使用groupbytransform创建两个总和然后除以如下方式创建列:

data[['pop0_sum', 'pop1_sum']] = data.groupby(['city0', 'city1'])[['pop0', 'pop1']].transform('sum')
data['w_mean'] = data['pop0_sum'] / data['pop1_sum']

结果:

    year  pop0  pop1   city0   city1  pop0_sum  pop1_sum    w_mean
0   2019    20    40  Malibu     NYC        60       120  0.500000
1   2018    60     8  Dublin  Sydney       115        13  8.846154
2   2018    23    36  Malibu     NYC        60       120  0.500000
3   2020    17    44  Malibu     NYC        60       120  0.500000
4   2019    55     5  Dublin  Sydney       115        13  8.846154

现在可以删除任何额外的列。

如果结果w_mean列应始终小于零,则可以按如下方式进行最后一次除法:

data['w_mean'] = np.where(data['pop0_sum'] > data['pop1_sum'], data['pop1_sum'] / data['pop0_sum'], data['pop0_sum'] / data['pop1_sum'])

这将为0.5马里布和纽约市对以及0.113043都柏林和悉尼提供。


推荐阅读