Упорядочить DataFrame по количеству строк col1 и категории - PullRequest
0 голосов
/ 07 июля 2019

Я хочу упорядочить этот 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 Пола, поэтому они подходят сначала, затем 2 Майкла и, наконец, только 1 Райан.

Ответы [ 3 ]

4 голосов
/ 07 июля 2019

Один вариант: используйте 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
3 голосов
/ 07 июля 2019

Необходимо создать вспомогательный столбец для сортировки, в данном случае size групп имен.Добавьте .reset_index(drop=True), если вы предпочитаете новый RangeIndex, или оставьте как есть, если оригинальный индекс полезен.

Сортировка не меняет порядок в пределах одинаковых значений, поэтому всегда будет появляться первая строка '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)
0 голосов
/ 07 июля 2019

Единственное добавленное мной изменение - возможность сортировки по количеству имен и возрасту.

    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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...