我想通过给定的列字段和该给定字段的条目数来排序此DataFrame。
因此,假设我有一个非常简单的数据框,看起来像这样:
name age
0 Paul 12
1 Ryan 17
2 Michael 100
3 Paul 36
4 Paul 66
5 Michael 45
我想要的结果是
name age
0 Paul 12
1 Paul 36
2 Paul 66
3 Michael 100
4 Michael 45
5 Ryan 17
所以我有3个Paul,所以他们首先出现,然后是2个Michael,最后只有1个Ryan。
答案 0 :(得分:4)
一个选项:使用value_counts
获取最常用的名称,然后设置,排序和重置索引:
x = list(df['name'].value_counts().index)
df.set_index('name').loc[x].reset_index()
返回
name age
0 Paul 12
1 Paul 36
2 Paul 66
3 Michael 100
4 Michael 45
5 Ryan 17
答案 1 :(得分:3)
需要创建一个帮助列进行排序,在这种情况下,名称列为size
。如果您希望使用全新的RangeIndex,请添加一个.reset_index(drop=True)
;如果原始Index有用,请保持原样。
排序不会改变相等值内的顺序,因此第一行'Paul'
将始终在'Paul'
内首先出现
(df.assign(s = df.groupby('name').name.transform('size'))
.sort_values('s', ascending=False)
.drop(columns='s'))
name age
0 Paul 12
3 Paul 36
4 Paul 66
2 Michael 100
5 Michael 45
1 Ryan 17
为减轻评论中的恐惧,此方法是有效的。比上述方法要重要得多。另外,您不会破坏初始索引。
import numpy as np
np.random.seed(42)
N = 10**6
df = pd.DataFrame({'name': np.random.randint(1, 10000, N),
'age': np.random.normal(0, 1, N)})
%%timeit
(df.assign(s = df.groupby('name').name.transform('size'))
.sort_values('s', ascending=False)
.drop(columns='s'))
#500 ms ± 31.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
x = list(df['name'].value_counts().index)
df.set_index('name').loc[x].reset_index()
#2.67 s ± 166 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
答案 2 :(得分:0)
我添加的唯一更改是可以按姓名计数和年龄进行排序的功能。
df['name_count'] = df['name'].map(df['name'].value_counts())
df = df.sort_values(by=['name_count', 'age'],
ascending=[False,True]).drop('name_count', axis=1)
df.reset_index(drop=True)
name age
0 Paul 12
1 Paul 36
2 Paul 66
3 Michael 45
4 Michael 100
5 Ryan 17