2016-08-07 30 views
1

Warum können Sie beim Schneiden eines Multi-Index-Datenrahmens eine einfachere Syntax verwenden, solange Sie den Level-0-Index schneiden? Hier ist ein Beispiel Datenrahmen:Warum scheint Pandas Multi-Index Dataframe Slicing inkonsistent zu sein?

  hi 
a b c  
1 foo baz 0 
     can 1 
    bar baz 2 
     can 3 
2 foo baz 4 
     can 5 
    bar baz 6 
     can 7 
3 foo baz 8 
     can 9 
    bar baz 10 
     can 11 

Diese Arbeit:

df.loc[1, 'foo', :] 
df.loc[1, :, 'can'] 

Während dies nicht:

df.loc[:, 'foo', 'can'] 

zwingt mich eine dieser stattdessen zu verwenden:

df.loc[(slice(None), 'foo', 'can'), :] 
df.loc[pd.IndexSlice[:, 'foo', 'can'], :] 

Im Folgenden sind die gleichen Beispiele, aber mit mehr Details l:

In [1]: import pandas as pd 
import numpy as np 

ix = pd.MultiIndex.from_product([[1, 2, 3], ['foo', 'bar'], ['baz', 'can']], names=['a', 'b', 'c']) 
data = np.arange(len(ix)) 
df = pd.DataFrame(data, index=ix, columns=['hi']) 
print df 

      hi 
a b c  
1 foo baz 0 
     can 1 
    bar baz 2 
     can 3 
2 foo baz 4 
     can 5 
    bar baz 6 
     can 7 
3 foo baz 8 
     can 9 
    bar baz 10 
     can 11 

In [2]: df.sort_index(inplace=True) 
print df.loc[1, 'foo', :] 

      hi 
a b c  
1 foo baz 0 
     can 1 

In [3]: print df.loc[1, :, 'can'] 

      hi 
a b c  
1 bar can 3 
    foo can 1 

In [4]: print df.loc[:, 'foo', 'can'] 

KeyError: 'the label [foo] is not in the [columns]' 

In [5]: print df.loc[(slice(None), 'foo', 'can'), :] 

      hi 
a b c  
1 foo can 1 
2 foo can 5 
3 foo can 9 

In [6]: print df.loc[pd.IndexSlice[:, 'foo', 'can'], :] 

      hi 
a b c  
1 foo can 1 
2 foo can 5 
3 foo can 9 

Antwort

1

Alle drei Beispiele sind technisch nicht eindeutig, es ist nur in den ersten beiden, pandas errät Ihre korrekt Absicht. Da das Spalten von Zeilen, Spalten auswählen (dh df.loc[:, columns] ist ein allgemeines Idiom, scheint die Ableitung diese Interpretation zu wählen.

Die Inferenz ist eine Art chaotisch, also ich denke, es ist viel besser, explizit zu sein. Es ist nicht so viel extra tippen wenn Sie alias IndexSlice

idx = pd.IndexSlice 
df.loc[idx[1, 'foo'], :] 
df.loc[idx[1, :, 'can'], :] 
df.loc[idx[:, 'foo', 'can'], :] 
+0

Warum ist 'df.loc [:, Spalten]' ein gemeinsames Idiom, wenn 'df [Spalten]' scheint das gleiche zu tun? ich bin wahrscheinlich etwas Nuance fehlt. – MarredCheese

+0

es in der Regel tut das gleiche ... außer wenn es nicht wegen Fallbacks ist.Es gibt ein Problem auf dem GitHub, das alle Möglichkeiten aufzählt - https://github.com/pydata/pandas/issues/9595 - wie dort angemerkt, ist es ein bisschen Chaos, an diesem Punkt primär für Rückwärtskompatibilität – chrisb

+0

Oh, ok. Vielen Dank! – MarredCheese