Сортировка по внешнему мультииндексу

#python #pandas #multi-index

#python #панды #многоиндексный

Вопрос:

Я хочу отсортировать фрейм данных от наивысшего к наименьшему на основе столбца B. Я не могу найти ответ о том, как сортировать внешний (т. Е. Первый) столбец индекса.

У меня есть этот пример данных:

                   A         B
Item    Type
0       X         'rtr'     2
        Tier      'sfg'     104
1       X         'zad'     7
        Tier      'asd'     132
2       X         'frs'     4
        Tier      'plg'     140
3       X         'gfq'     9
        Tier      'bcd'     100
  

Каждая строка с несколькими индексами содержит строку «Уровня». Я хочу отсортировать внешний индексный «Элемент» на основе значения столбца «B», относящегося к каждому «Уровню». Столбец «A» можно игнорировать для целей сортировки, но его необходимо включить в фрейм данных.

                   A         B
Item    Type
2       X         'frs'     4
        Tier      'plg'     140
1       X         'zad'     7
        Tier      'asd'     132
0       X         'rtr'     2
        Tier      'sfg'     104
3       X         'gfq'     9
        Tier      'bcd'     100
  

Комментарии:

1. используйте .sort_values('A') перед .groupby() . Он также будет отсортирован

2. можете ли вы поделиться своими необработанными данными, чтобы мы могли попытаться решить проблему сортировки.

3. Конечно, вот необработанные данные в формате CSV: pastebin.com/raw/8nJnURk7 Столбец «Итого» представляет собой букву «В» в этом вопросе. Индексы «Item» и «Type» и строка «Tier» имеют одно и то же имя, чтобы было понятно, в этом случае элементы 2, 4, 7 должны быть вверху (поскольку общие значения уровня равны 23), а элементы 0, 1, 3, 5, 6 должны быть внизу(поскольку общие значения уровня равны 22)

4. Итак, вы хотите отсортировать по элементу, затем по «B», а затем по «Типу». Правильно? Если да, то не 0 будет ли это первым элементом в списке? В качестве альтернативы, если вы хотите отсортировать по B, затем по элементу, тогда введите, не будет ли 2 в ‘B’ первым элементом, чтобы фрейм данных сортировался по элементу как 0, затем 2, затем 1, затем 7

5. Нет, это должно быть 2, 1, 0, 3. Строка (элемент) полного / внешнего индекса должна перемещаться выше или ниже в зависимости от ее значения в столбце B только для строки уровня. Причина, по которой я сформулировал вопрос таким образом, заключалась в том, что я видел предыдущий вопрос, в котором предлагается перемещать только строки внутреннего индекса (сохраняя при этом порядок первого / внешнего индекса одинаковым)

Ответ №1:

Новый ответ # 2

На основе всех полученных входных данных, вот решение. Надеюсь, это сработает для вас.

 import pandas as pd

df = pd.read_csv("xyz.txt")

df1 = df.copy()
#capture the original index of each row. This will be used for sorting later
df1['idx'] = df1.index

#create a dataframe with only items that match 'Tier'
#assumption is each Index has a row with 'Tier'
tier = df1.loc[df1['Type']=='Tier']

#sort Total for only the Tier rows
tier = tier.sort_values('Total')

#Create a list of the indexes in sorted order
#this will be the order to print the rows
tier_list = tier['Index'].tolist()

# Create the dictionary that defines the order for sorting
sorterIndex = dict(zip(tier_list, range(len(tier_list))))

# Generate a rank column that will be used to sort the dataframe numerically
df1['Tier_Rank'] = df1['Index'].map(sorterIndex)

#Now sort the dataframe based on rank column and original index
df1.sort_values(['Tier_Rank','idx'],ascending = [True, True],inplace = True)

#drop the temporary column we created
df1.drop(['Tier_Rank','idx'], 1, inplace = True)

#print the dataframe
print (df1)
  

На основе исходных данных, вот окончательный результат. Дайте мне знать, соответствует ли это тому, что вы искали.

     Index         Type                     Id  ...  Intellect  Strength  Total
12      2  Chest Armor  "6917529202229928161"  ...         17         8     62
13      2    Gauntlets  "6917529202229927889"  ...         16        14     60
14      2       Helmet  "6917529202223945870"  ...         10         9     66
15      2    Leg Armor  "6917529202802011569"  ...         15         2     61
16      2          Set                    NaN  ...         58        33    249
17      2         Tier                    NaN  ...          5         3     22
24      4  Chest Armor  "6917529202229928161"  ...         17         8     62
25      4    Gauntlets  "6917529202802009244"  ...          7         9     63
26      4       Helmet  "6917529202223945870"  ...         10         9     66
27      4    Leg Armor  "6917529202802011569"  ...         15         2     61
28      4          Set                    NaN  ...         49        28    252
29      4         Tier                    NaN  ...          4         2     22
42      7  Chest Armor  "6917529202229928161"  ...         17         8     62
43      7    Gauntlets  "6917529202791088503"  ...          7        14     61
44      7       Helmet  "6917529202223945870"  ...         10         9     66
45      7    Leg Armor  "6917529202229923870"  ...          7        19     57
46      7          Set                    NaN  ...         41        50    246
47      7         Tier                    NaN  ...          4         5     22
0       0  Chest Armor  "6917529202229928161"  ...         17         8     62
1       0    Gauntlets  "6917529202778947311"  ...         10        15     62
2       0       Helmet  "6917529202223945870"  ...         10         9     66
3       0    Leg Armor  "6917529202802011569"  ...         15         2     61
4       0          Set                    NaN  ...         52        34    251
5       0         Tier                    NaN  ...          5         3     23
6       1  Chest Armor  "6917529202229928161"  ...         17         8     62
7       1    Gauntlets  "6917529202778947311"  ...         10        15     62
8       1       Helmet  "6917529202223945870"  ...         10         9     66
9       1    Leg Armor  "6917529202229923870"  ...          7        19     57
10      1          Set                    NaN  ...         44        51    247
11      1         Tier                    NaN  ...          4         5     23
18      3  Chest Armor  "6917529202229928161"  ...         17         8     62
19      3    Gauntlets  "6917529202229927889"  ...         16        14     60
20      3       Helmet  "6917529202223945870"  ...         10         9     66
21      3    Leg Armor  "6917529202229923870"  ...          7        19     57
22      3          Set                    NaN  ...         50        50    245
23      3         Tier                    NaN  ...          5         5     23
30      5  Chest Armor  "6917529202229928161"  ...         17         8     62
31      5    Gauntlets  "6917529202802009244"  ...          7         9     63
32      5       Helmet  "6917529202223945870"  ...         10         9     66
33      5    Leg Armor  "6917529202229923870"  ...          7        19     57
34      5          Set                    NaN  ...         41        45    248
35      5         Tier                    NaN  ...          4         4     23
36      6  Chest Armor  "6917529202229928161"  ...         17         8     62
37      6    Gauntlets  "6917529202791088503"  ...          7        14     61
38      6       Helmet  "6917529202223945870"  ...         10         9     66
39      6    Leg Armor  "6917529202802011569"  ...         15         2     61
40      6          Set                    NaN  ...         49        33    250
41      6         Tier                    NaN  ...          4         3     23

[48 rows x 11 columns]
  

Новый ответ:

На основе общего файла исходных данных, вот группировка и сортировка. Дайте мне знать, как вы хотите, чтобы значения были отсортированы. Я предположил, что вы хотите, чтобы он был отсортирован по индексу, а затем по сумме.

 df = df.groupby(['Index','Type',])
       .agg({'Total':'mean'})
       .sort_values(['Index','Total'])
  

Результат этого будет следующим:

                    Total
Index Type              
0     Tier            23
      Leg Armor       61
      Chest Armor     62
      Gauntlets       62
      Helmet          66
      Set            251
1     Tier            23
      Leg Armor       57
      Chest Armor     62
      Gauntlets       62
      Helmet          66
      Set            247
2     Tier            22
      Gauntlets       60
      Leg Armor       61
      Chest Armor     62
      Helmet          66
      Set            249
3     Tier            23
      Leg Armor       57
      Gauntlets       60
      Chest Armor     62
      Helmet          66
      Set            245
4     Tier            22
      Leg Armor       61
      Chest Armor     62
      Gauntlets       63
      Helmet          66
      Set            252
  

Первоначальный ответ:

У меня нет ваших необработанных данных. Создал некоторые данные, чтобы показать вам, как сортировка будет работать с данными groupby. Посмотрите, это ли то, что вы ищете.

импортируйте pandas как pd

 df = pd.DataFrame({'Animal': ['Falcon', 'Falcon','Parrot', 'Parrot'],
                   'Type':['Wild', 'Captive', 'Wild', 'Captive'],
                   'Air': ['Good','Bad', 'Bad', 'Good'],
                   'Max Speed': [380., 370., 24., 26.]})

df = df.groupby(['Animal','Type','Air'])
       .agg({'Max Speed':'mean'})
       .sort_values('Max Speed')
print(df)
  

Результат будет следующим:

                      Max Speed
Animal Type    Air            
Parrot Wild    Bad        24.0
       Captive Good       26.0
Falcon Captive Bad       370.0
       Wild    Good      380.0
  

Без команды сортировки результат будет немного отличаться.

 df = df.groupby(['Animal','Type','Air'])
       .agg({'Max Speed':'mean'})
  

Это приведет к следующему. Максимальная скорость не сортируется. Вместо этого он использует группу по виду животного, а затем вводит:

                      Max Speed
Animal Type    Air            
Falcon Captive Bad       370.0
       Wild    Good      380.0
Parrot Captive Good       26.0
       Wild    Bad        24.0
  

Комментарии:

1. Порядок строк в «типе» должен оставаться таким же, как и в оригинале. Должна измениться только позиция индекса (в зависимости от значения уровня в общем столбце). Также другой столбец «A» должен оставаться в dataframe. Таким образом, 0, 1 и 3 должны быть вверху, потому что они имеют самые высокие уровни (23), в то время как 2 и 4 должны быть внизу (имеют только уровни 22)