Python 在pandas中,如何根据另一列的平均值创建具有排名的新列
我有下面的数据框Python 在pandas中,如何根据另一列的平均值创建具有排名的新列,python,pandas,Python,Pandas,我有下面的数据框 +---------+-------+ | Country | value | +---------+-------+ | UK | 42 | | US | 9 | | US | 10 | | France | 15 | | France | 16 | | Germany | 17 | | Germany | 18 | | Germany | 20 | +---------+-------+
+---------+-------+
| Country | value |
+---------+-------+
| UK | 42 |
| US | 9 |
| US | 10 |
| France | 15 |
| France | 16 |
| Germany | 17 |
| Germany | 18 |
| Germany | 20 |
+---------+-------+
我想创建一个新的专栏,根据每个国家价值的平均值从大到小对它们进行排名
输出如下所示
+---------+-------+---------+------+
| Country | value | Average | Rank |
+---------+-------+---------+------+
| UK | 42 | 42 | 1 |
| US | 9 | 9.5 | 4 |
| US | 10 | 9.5 | 4 |
| France | 15 | 15.5 | 3 |
| France | 16 | 15.5 | 3 |
| Germany | 17 | 18 | 2 |
| Germany | 18 | 18 | 2 |
| Germany | 20 | 18 | 2 |
+---------+-------+---------+------+
请注意,我不需要平均列,它只是用来帮助解释
非常感谢解决方案
我使用
pd.DataFrame.join
和pd.concat
组合使用groupby
和mean
m = df.groupby('Country').value.mean()
df.join(
pd.concat([m, m.rank(ascending=False)], axis=1, keys=['Average', 'Rank']),
on='Country')
Country value Average Rank
0 UK 42 42.000000 1.0
1 US 9 9.500000 4.0
2 US 10 9.500000 4.0
3 France 15 15.500000 3.0
4 France 16 15.500000 3.0
5 Germany 17 18.333333 2.0
6 Germany 18 18.333333 2.0
7 Germany 20 18.333333 2.0
类似地,使用双
连接
m = df.groupby('Country').value.mean()
df.join(m.rename('Avergage'), on='Country') \
.join(m.rank(ascending=False).rename('Rank'), on='Country')
Country value Average Rank
0 UK 42 42.000000 1.0
1 US 9 9.500000 4.0
2 US 10 9.500000 4.0
3 France 15 15.500000 3.0
4 France 16 15.500000 3.0
5 Germany 17 18.333333 2.0
6 Germany 18 18.333333 2.0
7 Germany 20 18.333333 2.0
或者使用
map
和assign
m = df.groupby('Country').value.mean()
df.assign(
Average=df.Country.map(m),
Rank=df.Country.map(m.rank(ascending=False))
)
Country value Average Rank
0 UK 42 42.000000 1.0
1 US 9 9.500000 4.0
2 US 10 9.500000 4.0
3 France 15 15.500000 3.0
4 France 16 15.500000 3.0
5 Germany 17 18.333333 2.0
6 Germany 18 18.333333 2.0
7 Germany 20 18.333333 2.0
使用+表示平均值,然后:
类似的解决方案:
a = df.groupby('Country')['value'].transform('mean')
b = a.rank(method='dense', ascending=False)
df = df.assign(Average=a, Rank=b)
print (df)
Country value Average Rank
0 UK 42 42.000000 1.0
1 US 9 9.500000 4.0
2 US 10 9.500000 4.0
3 France 15 15.500000 3.0
4 France 16 15.500000 3.0
5 Germany 17 18.333333 2.0
6 Germany 18 18.333333 2.0
7 Germany 20 18.333333 2.0
我会使用现代方法链接方法来避免状态突变和创建新变量:
df = pd.DataFrame(
{'Country': ['Russia', 'Russia', 'USA'], 'Value': [12, 15, 16]})
df.join(df.groupby('Country').
mean().
rank().
rename(columns={'Value': 'Rank'}),
on='Country')
很有趣,但对两个价值相同的国家不起作用。你能举个例子吗?我尝试了
{'Country':['rusia','USA'],'Value':[15,15]}
,它给出了排名:[1.5,1.5]
,这似乎是一个正确的答案。Nvm,通过排名(method=“dense”)解决了我看到的“问题”。(+1)是的,这就是排名的定义:如果有七个相等的值,它们共享可能排名的平均值。在这种情况下,最大秩等于元素数,这很好。对不起,我编辑了你的文章,这是一个建议。超级清晰和简洁。虽然采用了相同的方法,但看不到类似解决方案的意义。也许你的看法不同+1@AntonvBR-非常感谢!
df = pd.DataFrame(
{'Country': ['Russia', 'Russia', 'USA'], 'Value': [12, 15, 16]})
df.join(df.groupby('Country').
mean().
rank().
rename(columns={'Value': 'Rank'}),
on='Country')