Сортировать уровень данных мультикадра и по столбцу - PullRequest
0 голосов
/ 28 апреля 2018

Обновлено: версия 0.23.0 для панд решает эту проблему с

Сортировка по комбинации столбцов и уровней индекса


Я боролся с этим и подозреваю, что есть лучший способ. Как отсортировать следующий фрейм данных по имени уровня индекса 'idx_0', level = 0 и по столбцу, 'value_1' по убыванию, чтобы столбец "MyName" читал по вертикали "SCOTTBOSTON".

import pandas as pd
import numpy as np
df = pd.DataFrame({'idx_0':[2]*6+[1]*5,
                   'idx_1':[6,4,2,10,18,5,11,1,7,9,3],
                   'value_1':np.arange(11,0,-1),
                   'MyName':list('BOSTONSCOTT')})

df = df.set_index(['idx_0','idx_1'])
df

Выход:

            MyName  value_1
idx_0 idx_1                
2     6          B       11
      4          O       10
      2          S        9
      10         T        8
      18         O        7
      5          N        6
1     11         S        5
      1          C        4
      7          O        3
      9          T        2
      3          T        1

Исключен вывод с использованием:

df.sort_values(['value_1'], ascending=False)\
  .reindex(sorted(df.index.get_level_values(0).unique()), level=0)

Я подозреваю, что есть более простой способ без сброса индексов.

            MyName  value_1
idx_0 idx_1                
1     11         S        5
      1          C        4
      7          O        3
      9          T        2
      3          T        1
2     6          B       11
      4          O       10
      2          S        9
      10         T        8
      18         O        7
      5          N        6

Ошибка № 1:

df.sort_values('value_1', ascending=False).sort_index(level=0)

Сортировка сначала по значениям, а затем сортировка индекса level = 0, но также сортируются level = 1.

            MyName  value_1
idx_0 idx_1                
1     1          C        4
      3          T        1
      7          O        3
      9          T        2
      11         S        5
2     2          S        9
      4          O       10
      5          N        6
      6          B       11
      10         T        8
      18         O        7

Ошибка № 2

df.sort_index(level=0).sort_values('value_1', ascending=False)

Сортировка по уровню индекса = 0, затем сортировка по значениям, но индекс = 0 снова перемешивается.

            MyName  value_1
idx_0 idx_1                
2     6          B       11
      4          O       10
      2          S        9
      10         T        8
      18         O        7
      5          N        6
1     11         S        5
      1          C        4
      7          O        3
      9          T        2
      3          T        1

Ответы [ 3 ]

0 голосов
/ 28 апреля 2018

Вот несколько потенциальных решений для ваших нужд:

Способ-1:

 (df.sort_values('value_1', ascending=False)
    .sort_index(level=[0], ascending=[True]))

Способ-2:

 (df.set_index('value_1', append=True)
    .sort_index(level=[0,2], ascending=[True,False])
    .reset_index('value_1'))

Проверено на пандах 0.22.0, Python 3.6.4

0 голосов
/ 29 апреля 2018

Обновление с использованием панд версии 0.23.0

Сортировка по комбинации столбцов и уровней индекса

df.sort_values(by=['idx_0','value_1'], ascending=[True,False])

выход:

             value_1 MyName
idx_0 idx_1                
1     11           5      S
      1            4      C
      7            3      O
      9            2      T
      3            1      T
2     6           11      B
      4           10      O
      2            9      S
      10           8      T
      18           7      O
      5            6      N

Интересно, что @jxc указал на решение, которое, как я думал, должно работать, и было почти точно так же, как мой первый сбой.

df.sort_values('value_1', ascending=False)\
  .sort_index(level=0, ascending=[True])

Передача ascending в виде списка делает приведенный выше оператор работать как исключение. Я думаю, что в пандах передача скалярного значения и списка из них должна работать одинаково. Тем не менее, в этом случае, похоже, не работает так же.

Я отправлю сообщение об ошибке.

0 голосов
/ 28 апреля 2018

Вот мой уродливый вариант:

In [139]: (df.assign(x=df.index.get_level_values(0) * \
                       10**np.ceil(np.log10(df.value_1.max()))-df.value_1)
             .sort_values('x')
             .drop('x',1))
Out[139]:
            MyName  value_1
idx_0 idx_1
1     11         S        5
      1          C        4
      7          O        3
      9          T        2
      3          T        1
2     6          B       11
      4          O       10
      2          S        9
      10         T        8
      18         O        7
      5          N        6

некоторые объяснения:

In [140]: np.ceil(np.log10(df.value_1.max()))
Out[140]: 2.0

In [141]: df.assign(x=df.index.get_level_values(0)*10**np.ceil(np.log10(df.value_1.max()))-df.value_1)
Out[141]:
            MyName  value_1      x
idx_0 idx_1
2     6          B       11  189.0
      4          O       10  190.0
      2          S        9  191.0
      10         T        8  192.0
      18         O        7  193.0
      5          N        6  194.0
1     11         S        5   95.0
      1          C        4   96.0
      7          O        3   97.0
      9          T        2   98.0
      3          T        1   99.0

другой вариант - добавить idx_0 сортировку по нему и по value_1 и удалить этот дополнительный столбец:

In [142]: (df.assign(x=df.index.get_level_values(0)).sort_values(['x', 'value_1'], ascending=[1,0])
             .drop('x',1))
Out[142]:
            MyName  value_1
idx_0 idx_1
1     11         S        5
      1          C        4
      7          O        3
      9          T        2
      3          T        1
2     6          B       11
      4          O       10
      2          S        9
      10         T        8
      18         O        7
      5          N        6
...