2015-10-18 20 views
7

Istnieje wiele postów na temat wycinania poziomu [0] wieluindeksów o zakresie poziomu 1. Jednak nie mogę znaleźć rozwiązania dla mojego problemu; to znaczy, potrzebuję zakresu indeksu poziomu 1 dla wartości wskaźnika poziomu [0]Python Pandas slice multiindex według drugiego poziomu indeksu (lub dowolnego innego poziomu)

ramka danych: Pierwsza to od A do Z, pozycja od 1 do 400; Potrzebuję pierwszych 2 i ostatnich 2 dla każdego poziomu [0] (Pierwszy), ale nie w tym samym kroku.

  Title Score 
First Rank 
A  1 foo 100 
     2 bar 90 
     3 lime 80 
     4 lame 70 
B  1 foo 400 
     2 lime 300 
     3 lame 200 
     4 dime 100 

Próbuję dostać ostatnie 2 wiersze dla każdego indeksu poziom 1 z poniższym kodzie, ale właściwie tylko plastry na pierwszym poziomie [0] wartości.

[IN] df.ix[x.index.levels[1][-2]:] 
[OUT] 
       Title Score 
    First Rank 
    A  3 lime 80 
      4 lame 70 
    B  1 foo 400 
      2 lime 300 
      3 lame 200 
      4 dime 100 

Pierwsze 2 rzędy otrzymuję przez zamianę indeksów, ale nie mogę sprawić, żeby działał przez ostatnie 2 rzędy.

df.index = df.index.swaplevel("Rank", "First") 
df= df.sortlevel() #to sort by Rank 
df.ix[1:2] #Produces the first 2 ranks with 2 level[1] (First) each. 
      Title Score 
Rank First 
1  A foo 100 
     B foo 400 
2  A bar 90 
     B lime 300 

Oczywiście mogę zamienić to z powrotem, aby uzyskać w ten sposób:

df2 = df.ix[1:2] 
df2.index = ttt.index.swaplevel("First","rank") #change the order of the indices back. 
df2.sortlevel() 
       Title Score 
    First Rank 
    A  1 foo 100 
      2 bar 90 
    B  1 foo 400 
      2 lime 300 

Każda pomoc jest mile widziana, aby dostać się z tą samą procedurą:

  • ostatnie 2 wiersze dla indeksu 1 (Rank)
  • I lepszy sposób na uzyskanie pierwszych 2 rzędów

Edit następujących informacji zwrotnej przez @ako:

Korzystanie pd.IndexSlice naprawdę ułatwia pokroić dowolny wskaźnik poziomu. Tutaj bardziej ogólne rozwiązanie i poniżej mojego stopniowego podejścia do uzyskania pierwszego i dwóch ostatnich wierszy. Więcej informacji tutaj: http://pandas.pydata.org/pandas-docs/stable/advanced.html#using-slicers

"""  
Slicing a dataframe at the level[2] index of the 
major axis (row) for specific and at the level[1] index for columns. 

""" 
    df.loc[idx[:,:,['some label','another label']],idx[:,'yet another label']] 

""" 
Thanks to @ako below is my solution, including how I 
get the top and last 2 rows. 
""" 
    idx = pd.IndexSlice 
    # Top 2 
    df.loc[idx[:,[1,2],:] #[1,2] is NOT a row index, it is the rank label. 
    # Last 2 
    max = len(df.index.levels[df.index.names.index("rank")]) # unique rank labels 
    last2=[x for x in range(max-2,max)] 
    df.loc[idx[:,last2],:] #for last 2 - assuming all level[0] have the same lengths. 

Odpowiedz

10

Użyj podziałowe pokroić dowolne wartości w dowolnych wymiarach - po prostu przekazać listę z tym, co pożądane poziomy/wartości dla tego wymiaru.

idx = pd.IndexSlice 
df.loc[idx[:,[3,4]],:] 

      Title Score 
First Rank    
A  3  lime  80 
     4  lame  70 
B  3  lame 200 
     4  dime 100 

Do odtwarzania danych:

from StringIO import StringIO 

s=""" 
First Rank Title Score 
A  1 foo 100 
A  2 bar 90 
A  3 lime 80 
A  4 lame 70 
B  1 foo 400 
B  2 lime 300 
B  3 lame 200 
B  4 dime 100 
""" 
df = pd.read_csv(StringIO(s), 
       sep='\s+', 
       index_col=["First", "Rank"]) 
+2

Przez odpowiedziach na całym StackOverflow do indeksowania MultiIndex Pand, to rozwiązanie wydaje się zarówno do najczystszych i dość niedoceniany. –

Powiązane problemy