2015-10-17 4 views
7

В Pandas 0.17 Я пытаюсь сортировать по определенному столбцу, сохраняя иерархический индекс (A и B). B - это рабочий номер, созданный при настройке блока данных посредством конкатенации. Мои данные выглядит следующим образом:Python Pandas sorting by multiindex и column

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

Это то, что мне нужно:

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

Ниже приведен код, я использую и результат. Примечание. Pandas 0.17 предупреждает, что dataframe.sort будет устаревшим.

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 

Добавление .groupby производит тот же результат:

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

Аналогично, переключение сортировки индексов, а затем GroupBy столбец не плодотворными:

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

Я не уверен о переиндексации Мне нужно сохранить первый индекс A, второй индекс B можно переназначить, но не нужно. Меня это удивило бы, если бы не было простого решения; Наверное, я просто не нахожу его. Любые предложения приветствуются.


Edit: В то же время я упал второй индекс B, переназначен первый индекс А быть столбец вместо индекса отсортированный несколько столбцов, а затем повторно индексируются его:

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") 

Еще очень подробный.

ответ

6

ощущению как там может быть лучше, но вот один подход:

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

Ваш подход более продвинут, чем мое промежуточное решение, но я согласен с тем, что должен быть лучший способ. – raummensch

1

на основе кода chrisb в:

Обратите внимание, что в моем случае, это серия не DataFrame,

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