2016-05-10 2 views
2

Учитывая эти данные кадра и сводной таблицы:Панды сводной таблицы Вложенные Сортировка

import pandas as pd 
df=pd.DataFrame({'A':['x','y','z','x','y','z'], 
       'B':['one','one','one','two','two','two'], 
       'C':[7,5,3,4,1,6]}) 
df 


    A B  C 
0 x one  7 
1 y one  5 
2 z one  3 
3 x two  4 
4 y two  1 
5 z two  6 

table = pd.pivot_table(df, index=['A', 'B'],aggfunc=np.sum) 

table 
A B 
x one 7 
    two 4 
y one 5 
    two 1 
z one 3 
    two 6 
Name: C, dtype: int64 

Я хочу, чтобы отсортировать таблицу поворота таким образом, что порядок «А» г, х, у и порядок «B 'основано на отсортированных по убыванию значениях из столбца кадра данных C.

Как это:

A B 
z two 6 
    one 3 
x one 7 
    two 4 
y one 5 
    two 1 

    Name: C, dtype: int64 

Спасибо заранее!

+0

'z, x , y' не сортируется в любом порядке. – Alexander

+0

Привет, Александр. Да, это потому, что я хочу иметь возможность настраивать порядок первого индекса. –

ответ

2

Я не верю, что есть простой способ достичь вашей цели. Следующее решение сначала сортирует вашу таблицу в порядке убывания, основанном на значениях столбца C. Затем он объединяет каждый фрагмент в соответствии с вашим желаемым порядком.

order = ['z', 'x', 'y'] 
table = table.reset_index().sort_values('C', ascending=False) 
>>> pd.concat([table.loc[table.A == val, :].set_index(['A', 'B']) for val in order]) 
     C 
A B  
z two 6 
    one 3 
x one 7 
    two 4 
y one 5 
    two 1 
+1

Очень приятно. :) Я пробую карту по словарю, но это лучше. – jezrael

1

Решение

custom_order = ['z', 'x', 'y'] 
kwargs = dict(axis=0, level=0, drop_level=False) 

new_table = pd.concat(
    [table.xs(idx_v, **kwargs).sort_values(ascending=False) for idx_v in custom_order] 
) 

Alternate один лайнер

pd.concat([table.xs(i, drop_level=0).sort_values(ascending=0) for i in list('zxy')] 

Объяснение

custom_order Ваш желаемый порядок. kwargs - удобный способ улучшить читаемость (на мой взгляд). Ключевые элементы, которые необходимо отметить, axis=0 и level=0 могут быть важны для вас, если вы хотите использовать это дальше. Однако они также являются значениями по умолчанию и могут быть опущены. drop_level=False является ключевым аргументом здесь и необходимо сохранить idx_v, мы принимаем xs, так что pd.concat объединяет все вместе так, как нам хотелось бы.

Я использую понимание списка почти так же, как Александр, в вызове pd.concat.

Демонстрация

print new_table 

A B 
z two 6 
    one 3 
x one 7 
    two 4 
y one 5 
    two 1 
Name: C, dtype: int64 
1

Если вы можете прочитать в колонке А в качестве категориальных данных, то становится гораздо проще. Установка ваших категорий как list('zxy') с указанием ordered=True использует ваш заказ.

Вы можете прочитать в ваших данных, используя что-то похожее на:

'A':pd.Categorical(['x','y','z','x','y','z'], list('zxy'), ordered=True) 

В качестве альтернативы, вы можете прочитать в данных, как вы в настоящее время, а затем использовать astype для преобразования А категоричен:

df['A'] = df['A'].astype('category', categories=list('zxy'), ordered=True) 

После того, как A категоричен, вы можете поворачивать то же самое, что и раньше, а затем сортировать по:

table = table.sort_values(ascending=False).sortlevel(0, sort_remaining=False) 
+0

Я не могу реализовать то, что вы упомянули. –

+1

Я отредактировал свой ответ с альтернативным способом преобразования в категориальные данные.Я предполагаю, что это часть, которую вы не можете реализовать? – root

+0

Спасибо, @root! Это прояснило это для меня. Из любопытства я вижу другой способ сделать это: df ['A'] = df ['A']. Astype ('category'), а затем в следующей строке df ['A']. Cat.set_categories (['z', 'x', 'y'], inplace = True) Является ли один метод лучше другого в определенных ситуациях? –

Смежные вопросы