2015-10-17 16 views
7

In Pandas 0.17 versuche ich nach einer bestimmten Spalte zu sortieren, während ich den hierarchischen Index (A und B) behalte. B ist eine laufende Nummer, die beim Einrichten des Datenrahmens durch Verkettung erstellt wird. Meine Daten sieht wie folgt aus:Python Pandas Sortierung nach Multiindex und Spalte

  C  D 
A B 
bar one shiny 10 
    two dull 5 
    three glossy 8 
foo one dull 3 
    two shiny 9 
    three matt 12 

Das ist, was ich brauche:

  C  D 
A B 
bar two dull 5 
    three glossy 8 
    one shiny 10 
foo one dull 3 
    three matt 12 
    two shiny 9 

Unten ist der Code Ich verwende und das Ergebnis. Hinweis: Pandas 0.17 warnt, dass dataframe.sort veraltet ist.

df.sort_values(by="C", ascending=True) 
      C  D 
A B 
bar two dull 5 
foo one dull 3 
bar three glossy 8 
foo three matt 12 
bar one shiny 10 
foo two shiny 9 

Hinzufügen .groupby erzeugt das gleiche Ergebnis:

df.sort_values(by="C", ascending=True).groupby(axis=0, level=0, as_index=True) 

Ähnlich zu Schalt Indizes erste Sortieranlage und dann groupby die Spalte nicht fruchtbar ist:

df.sort_index(axis=0, level=0, as_index=True).groupby(C, as_index=True) 

Ich bin nicht sicher, über Neuindizierung muss ich den ersten Index A behalten, zweiter Index B kann neu zugewiesen werden, muss aber nicht. Es würde mich überraschen, wenn es keine einfache Lösung gäbe; Ich denke, ich finde es einfach nicht. Irgendwelche Vorschläge werden geschätzt.


Edit: In der Zwischenzeit habe ich den zweiten Index B fallen gelassen, erste Index A zugewiesen, eine Spalte zu sein, anstatt ein Index mehrere Spalten sortiert, dann ist es wieder indiziert:

df.index = df.index.droplevel(1) 
df.reset_index(level=0, inplace=True) 
df_sorted = df.sort_values(["A", "C"], ascending=[1,1]) #A is a column here, not an index. 
df_reindexed = df_sorted.set_index("A") 

Noch sehr ausführlich.

Antwort

6

Fühlt es einen besseren Weg sein könnte, aber hier ist ein Ansatz:

In [163]: def sorter(sub_df): 
    ...:  sub_df = sub_df.sort_values('C') 
    ...:  sub_df.index = sub_df.index.droplevel(0) 
    ...:  return sub_df 

In [164]: df.groupby(level='A').apply(sorter) 
Out[164]: 
       C D 
A B     
bar two  dull 5 
    three glossy 8 
    one  shiny 10 
foo one  dull 3 
    three matt 12 
    two  shiny 9 
+0

Ihr Ansatz ist fortgeschrittener als meine Zwischenlösung, aber ich stimme zu, dass es einen besseren Weg geben sollte. – raummensch

1

Basierend auf chrisb Code:

Beachten Sie, dass in meinem Fall ist es eine Reihe kein Datenrahmen,

s.groupby(level='A', group_keys=False).apply(lambda x: x.sort_values(ascending=False))