Как удалить определенные значения в многоуровневом индексе python pandas

#python #pandas #dataframe #indexing

#python #pandas #фрейм данных #индексирование

Вопрос:

У меня есть нечто похожее на следующий фрейм данных, df :

 df
    full_name       team    rec_yards
0   Michael Thomas   NO        1688      
1   Chris Godwin     NO        1333      
2   DeAndre Hopkins  NO        1165     
3   Julio Jones      NO        1316    
4   Cooper Kupp      NO        800  
5   Adam Thielen     LA        1165     
6   Julian Edelman   LA        1316    
7   Stefon Diggs     LA        1062
8   Alshon Jeffery   LA        1250   
9   AJ Green         LA        800
...
  

Для каждого team я хотел бы сохранить первые четыре full_name в соответствии с rec_yards . Есть ли способ, которым я могу перебирать каждую команду, чтобы сделать это?

Это мой желаемый результат:

     full_name       team    rec_yards
0   Michael Thomas   NO        1688      
1   Chris Godwin     NO        1333
2   Julio Jones      NO        1316          
3   DeAndre Hopkins  NO        1165            
4   Julian Edelman   LA        1316    
5   Alshon Jeffery   LA        1250 
6   Adam Thielen     LA        1165 
7   Stefon Diggs     LA        1062
  

Этот вывод сохраняет четыре лучших rec_yards значения для каждой команды, сортирует их и удаляет все строки, которые не входят в топ-4 для каждой команды

Что я пробовал:

Я попытался превратить df в многоуровневый индекс, используя

 filter.set_index(['team', 'full_name']).sort_index()
  

Но rec_yards не сортируется в каком-либо определенном порядке. Опять же, я бы просто хотел сохранить 4 лучших full_name для каждого team в соответствии со rec_yards значениями. Является ли многоуровневый индекс правильным решением здесь? Примечание: исходный df не является многоуровневым индексом, как кто-то думал. Это просто исходный df.

РЕДАКТИРОВАТЬ: Вот словарь моего df

 {'full_name': ['Michael Thomas',
  'Chris Godwin',
  'DeAndre Hopkins',
  'Julio Jones',
  'Cooper Kupp',
  'Julian Edelman',
  'Kenny Golladay',
  'Keenan Allen',
  'Amari Cooper',
  'D.J. Moore',
  'Mike Evans',
  'DeVante Parker',
  'Jarvis Landry',
  'Stefon Diggs',
  'Tyler Lockett',
  'Tyler Boyd',
  'John Brown',
  'Robert Woods',
  'Courtland Sutton',
  'Calvin Ridley',
  'A.J. Brown',
  'Terry McLaurin',
  'Davante Adams',
  'Cole Beasley',
  'Michael Gallup',
  'Tyreek Hill',
  'Jamison Crowder',
  'Larry Fitzgerald',
  'Curtis Samuel',
  'Deebo Samuel',
  'Darius Slayton',
  'Mike Williams',
  'Mike Williams',
  'Robby Anderson',
  'Christian Kirk',
  'Diontae Johnson',
  'Chris Conley',
  'Randall Cobb',
  'Tyrell Williams',
  'Marquise Brown',
  'Sammy Watkins',
  'Golden Tate',
  'James Washington',
  'Dede Westbrook',
  'Danny Amendola',
  'Sterling Shepard',
  'Zach Pascal',
  'Anthony Miller',
  'Alshon Jeffery',
  'Kenny Stills',
  'T.Y. Hilton',
  'Adam Thielen',
  'Breshad Perriman',
  'Mecole Hardman',
  'JuJu Smith-Schuster',
  'Hunter Renfrow',
  'Brandin Cooks',
  'Corey Davis',
  'Auden Tate',
  'Emmanuel Sanders',
  'Emmanuel Sanders',
  'Alex Erickson',
  'Kendrick Bourne',
  'Nelson Agholor',
  'Preston Williams',
  'Demarcus Robinson',
  'Taylor Gabriel',
  'Russell Gage',
  'Adam Humphries',
  'Allen Lazard',
  'Allen Hurns',
  'Demaryius Thomas',
  'Marquez Valdes-Scantling',
  'Albert Wilson',
  'Bisi Johnson',
  'Geronimo Allison',
  'Paul Richardson',
  'Keelan Cole',
  'Cody Latimer',
  'Jakobi Meyers',
  'Josh Reynolds',
  'Kelvin Harmon',
  'Seth Roberts',
  'Isaiah McKenzie',
  'David Moore',
  'Josh Gordon',
  'Josh Gordon',
  "Tre'Quan Smith",
  'Jarius Wright',
  'Damiere Byrd',
  'Keke Coutee',
  'DaeSean Hamilton',
  'Pharoh Cooper',
  'Trey Quinn',
  'Miles Boykin',
  'Jaron Brown',
  'Chester Rogers',
  'Tavon Austin',
  'KeeSean Johnson',
  'Malik Turner',
  'Bennie Fowler',
  'Vyncint Smith',
  'Jakeem Grant',
  'Parris Campbell',
  'Marvin Hall',
  'Jake Kumerow',
  'Justin Watson',
  'Marquise Goodwin',
  'Javon Wims',
  'DeSean Jackson',
  'Andy Isabella',
  'Tim Patrick',
  'Byron Pringle',
  'Dante Pettis',
  'Laquon Treadwell',
  'J.J. Arcega-Whiteside',
  "N'Keal Harry",
  'Justin Hardy',
  'Kalif Raymond',
  'Zay Jones',
  'Zay Jones',
  'Trevor Davis',
  'Trevor Davis',
  'Trevor Davis',
  'Cordarrelle Patterson',
  'Keelan Doss',
  'Damion Ratley',
  'Mack Hollins',
  'Mack Hollins',
  'Devin Smith',
  'Dontrelle Inman',
  'Dontrelle Inman',
  'Christian Blake',
  'Duke Williams',
  'Antonio Callaway',
  'Olamide Zaccheaus',
  'Rashard Higgins',
  'Braxton Berrios',
  'DeAndre Carter',
  'Robert Foster',
  'Deon Cain',
  'Deon Cain',
  'Trent Sherfield',
  'Andre Patton',
  'Chris Hogan',
  'Ryan Switzer',
  'Diontae Spencer',
  'Deonte Harris',
  'Chad Beebe',
  'Marcell Ateman',
  'Travis Benjamin',
  'KhaDarel Hodge',
  'Ventell Bryant',
  'Geremy Davis',
  'Jason Moore',
  'Devin Funchess',
  'Johnny Holton',
  'Cody Core',
  'Donte Moncrief',
  'Andre Roberts',
  'Russell Shepard',
  'Gunner Olszewski',
  'Ryan Grant',
  'C.J. Board',
  'Chris Moore',
  'Marqise Lee',
  'Stanley Morgan',
  'Riley Ridley',
  'Fred Brown',
  'DeAndrew White',
  'Josh Bellamy',
  'Ashton Dulin',
  'Michael Walker',
  'Mike Thomas',
  'Brandon Zylstra',
  'Austin Carr',
  'Dwayne Harris',
  'Krishawn Hogan',
  'Quincy Enunwa',
  'Greg Dortch',
  'JoJo Natson',
  'Juwann Winfree',
  'Matthew Slater',
  'Taywan Taylor'],
 'rec_yards': [1688,
  1333,
  1165,
  1316,
  1062,
  1091,
  1118,
  1117,
  1097,
  1175,
  1157,
  1065,
  1092,
  1130,
  1006,
  987,
  1060,
  1067,
  1060,
  866,
  927,
  919,
  904,
  778,
  1009,
  799,
  767,
  759,
  614,
  700,
  690,
  963,
  963,
  761,
  649,
  626,
  737,
  747,
  651,
  569,
  665,
  608,
  735,
  588,
  662,
  537,
  597,
  651,
  490,
  561,
  429,
  418,
  511,
  508,
  546,
  503,
  543,
  557,
  575,
  477,
  367,
  513,
  358,
  363,
  428,
  425,
  353,
  378,
  374,
  408,
  416,
  433,
  433,
  292,
  260,
  270,
  245,
  294,
  288,
  359,
  326,
  332,
  271,
  247,
  271,
  287,
  139,
  178,
  286,
  285,
  247,
  232,
  219,
  198,
  198,
  220,
  179,
  176,
  187,
  245,
  193,
  189,
  164,
  127,
  261,
  212,
  132,
  186,
  163,
  159,
  189,
  204,
  170,
  109,
  184,
  169,
  76,
  155,
  170,
  126,
  69,
  83,
  28,
  0,
  83,
  133,
  136,
  125,
  0,
  113,
  132,
  43,
  91,
  58,
  89,
  93,
  55,
  104,
  97,
  64,
  72,
  52,
  80,
  56,
  53,
  27,
  31,
  24,
  70,
  70,
  30,
  57,
  15,
  38,
  43,
  32,
  21,
  28,
  18,
  20,
  25,
  34,
  14,
  31,
  21,
  18,
  18,
  15,
  21,
  20,
  20,
  17,
  15,
  14,
  10,
  9,
  7,
  4,
  -4,
  0,
  0,
  0,
  0,
  0],
 'team': ['NO',
  'TB',
  'HOU',
  'ATL',
  'LA',
  'NE',
  'DET',
  'LAC',
  'DAL',
  'CAR',
  'TB',
  'MIA',
  'CLE',
  'MIN',
  'SEA',
  'CIN',
  'BUF',
  'LA',
  'DEN',
  'ATL',
  'TEN',
  'WAS',
  'GB',
  'BUF',
  'DAL',
  'KC',
  'NYJ',
  'ARI',
  'CAR',
  'SF',
  'NYG',
  'LAC',
  'LAC',
  'NYJ',
  'ARI',
  'PIT',
  'JAC',
  'DAL',
  'OAK',
  'BAL',
  'KC',
  'NYG',
  'PIT',
  'JAC',
  'DET',
  'NYG',
  'IND',
  'CHI',
  'PHI',
  'HOU',
  'IND',
  'MIN',
  'TB',
  'KC',
  'PIT',
  'OAK',
  'LA',
  'TEN',
  'CIN',
  'SF',
  'DEN',
  'CIN',
  'SF',
  'PHI',
  'MIA',
  'KC',
  'CHI',
  'ATL',
  'TEN',
  'GB',
  'MIA',
  'NYJ',
  'GB',
  'MIA',
  'MIN',
  'GB',
  'WAS',
  'JAC',
  'NYG',
  'NE',
  'LA',
  'WAS',
  'BAL',
  'BUF',
  'SEA',
  'NE',
  'SEA',
  'NO',
  'CAR',
  'ARI',
  'HOU',
  'DEN',
  'ARI',
  'WAS',
  'BAL',
  'SEA',
  'IND',
  'DAL',
  'ARI',
  'SEA',
  'NYG',
  'NYJ',
  'MIA',
  'IND',
  'DET',
  'GB',
  'TB',
  'SF',
  'CHI',
  'PHI',
  'ARI',
  'DEN',
  'KC',
  'SF',
  'MIN',
  'PHI',
  'NE',
  'ATL',
  'TEN',
  'OAK',
  'BUF',
  'OAK',
  'GB',
  'MIA',
  'CHI',
  'OAK',
  'CLE',
  'PHI',
  'MIA',
  'DAL',
  'LAC',
  'IND',
  'ATL',
  'BUF',
  'CLE',
  'ATL',
  'CLE',
  'NYJ',
  'HOU',
  'BUF',
  'PIT',
  'IND',
  'ARI',
  'LAC',
  'CAR',
  'PIT',
  'DEN',
  'NO',
  'MIN',
  'OAK',
  'LAC',
  'CLE',
  'DAL',
  'LAC',
  'LAC',
  'IND',
  'PIT',
  'NYG',
  'PIT',
  'BUF',
  'NYG',
  'NE',
  'OAK',
  'JAC',
  'BAL',
  'JAC',
  'CIN',
  'CHI',
  'DEN',
  'CAR',
  'NYJ',
  'IND',
  'JAC',
  'LA',
  'CAR',
  'NO',
  'OAK',
  'NO',
  'NYJ',
  'CAR',
  'LA',
  'DEN',
  'NE',
  'CLE']}
  

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

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

2. Я отредактирую сообщение.

3. Проверьте еще раз @sammywemmy, я надеюсь, что это объяснено лучше.

4. Нам было бы проще, если бы вы показали содержимое вашего исходного фрейма данных в виде словаря. Вы можете сделать это с помощью этого: df.to_dict('list')

5. Опубликовал словарь моего df @Bill

Ответ №1:

Я думаю, это должно сработать:

 # Make a sorted multi-index
df_sorted = df.set_index(['team','rec_yards']).sort_index(ascending=False)

# Add a dummy column containing all 1s
df_sorted['count'] = 1

# Turn it into a ranking by team
df_sorted['count'] = df_sorted.groupby('team')['count'].cumsum()       

# Only keep the first n rows per team
n = 4
df_sorted = df_sorted.loc[df_sorted['count'] <= n]

# Re-arrange it however you prefer
df_sorted.reset_index().set_index(['team','count'])
  

Вывод:

             rec_yards        full_name
team count                            
WAS  1            919   Terry McLaurin
     2            332    Kelvin Harmon
     3            245  Paul Richardson
     4            198       Trey Quinn
TEN  1            927       A.J. Brown
     2            557      Corey Davis
     3            374   Adam Humphries
     4            170    Kalif Raymond
TB   1           1333     Chris Godwin
     2           1157       Mike Evans
  

Ответ №2:

Вы также можете использовать head метод с df.groupby :

 df.sort_values(['team','rec_yards'], ascending=False).groupby('team').head(4)
  

Вывод:

            full_name  rec_yards team
21    Terry McLaurin        919  WAS
81     Kelvin Harmon        332  WAS
76   Paul Richardson        245  WAS
93        Trey Quinn        198  WAS
20        A.J. Brown        927  TEN
57       Corey Davis        557  TEN
68    Adam Humphries        374  TEN
118    Kalif Raymond        170  TEN
1       Chris Godwin       1333   TB
10        Mike Evans       1157   TB
  

(Возможно, было бы хорошей идеей повторно проиндексировать фрейм данных после этого).

Лучшим решением было бы, если бы существовал способ использовать pd.DataFrame.nlargest с фреймом данных groupby, но, насколько я могу судить, вы не можете (есть, SeriesGroupBy.nlargest но не DataFrameGroupBy.nlargest ). Вы можете сделать это с помощью DataFrame.nlargest метода GroupBy.apply, но я протестировал его, и он довольно неэффективен:

 df.groupby('team').apply(pd.DataFrame.nlargest, 4, columns=['rec_yards'])
  

Вывод:

                  full_name  rec_yards team  count
team                                             
ARI  27   Larry Fitzgerald        759  ARI      1
     34     Christian Kirk        649  ARI      1
     89       Damiere Byrd        285  ARI      1
     92      Pharoh Cooper        219  ARI      1
ATL  3         Julio Jones       1316  ATL      1
     19      Calvin Ridley        866  ATL      1
     67       Russell Gage        378  ATL      1
     117      Justin Hardy        155  ATL      1
BAL  39     Marquise Brown        569  BAL      1
     82       Seth Roberts        271  BAL      1
  

Примечание: Вторым уровнем мультииндексации здесь является исходное значение индекса в df .