按col1的行数和类别对DataFrame进行排序

时间:2019-07-06 23:49:24

标签: python pandas sorting dataframe

我想通过给定的列字段和该给定字段的条目数来排序此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。

3 个答案:

答案 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