2015-02-24 3 views
0

Я создал сводную таблицу с трехуровневым мультииндексом (Group, Product и State). Уровень состояния автоматически сортируется в алфавитном порядке, но мне нужно изменить порядок заказа на пользовательский, не алфавитный порядок. Возможно, мне также придется переупорядочить уровни Group и Product аналогичным образом.Pandas Pivot Table - переопределить порядок мультииндекса

pivot = data.pivot_table(rows=['Group', 'Product', 'State'], 
        values = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 
           'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 
           'NOV', 'DEC'], fill_value=0, margins=True aggfunc=sum) 

cols = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'] 

#I used this method to prevent the month names from being alphabetically sorted 
pivot = pivot[cols] 

Часть сводной таблицы выглядит следующим образом ...

        JUN  JUL AUG 
Group Product  State 
Group A Product A AZ   0  0  0 
        CO   0  0  0 
        GA   0  0  0 
        IL   0  0  0 
        IN   0  0  0 
        KS   0  0  0 
        MN   0  0  0 
        MO   0  0  0 

мне нужна упорядоченность состояний быть следующим ...

state_order = ['AZ','CO','ID','NV','OR','UT','WA','IA','KS','MN','MO','NE','ND','SD','GA','IL','IN','OH','WI'] 

Я попытался reindex_axis() fuction, подача в моем списке выше и указание уровня = 2. Однако государства по-прежнему сортировались в алфавитном порядке.

Любое понимание исправления было бы высоко оценено.

+0

может быть дубликатом http://stackoverflow.com/questions/26707171/sort-pandas-dataframe-based-on-list – aensm

+0

Метод в сообщении выше очень хорошо работал для переупорядочения и отображения наблюдений в моем DataFrame; однако, когда я создал сводную таблицу из DataFrame, порядок изменяется. Состояния, которые были отсортированы в моем исходном DataFrame, применяются в алфавитном порядке. – marshackVB

+0

Я считаю, что мне нужен способ специально переупорядочить мультииндексный уровень уровня 2 сводной таблицы (имена состояний), предоставив список, хотя я попытался и не смог выполнить это. – marshackVB

ответ

1

Вы можете попробовать изменить тип данных состояния в категории.

data["state"] = data["state"].astype("category") 

затем установить порядок сортировки

data["state"].cat.set_categories(['AZ','CO','ID','NV','OR','UT','WA','IA','KS', 
        'MN','MO','NE','ND','SD','GA','IL','IN','OH','WI'],inplace=True) 

EDIT: FYI, категория DTYPE является относительно новым. 0.15.0 я считаю

+0

Благодарим вас за ответ. Я все еще не могу предотвратить отображение байт-указателя уровня 2, который представляет имена состояний, от использования в алфавитном порядке. DataFrame, основанный на сводной таблице, реорганизуется должным образом по состоянию. После создания сводной таблицы упорядочение изменяется. Кажется, что мне нужно специально переупорядочить мультииндекс сводной таблицы, а не данные DataFrame, на которых он основан. – marshackVB

+0

Что происходит при сбросе указателей поворота? Правильно ли он сортируется? –

+0

Я попробовал pivot.reset_index(), но состояния все еще отсортированы в алфавитном порядке, как и в исходной таблице. Я также попытался создать сводную таблицу, используя groupby() и unstack(). Тем не менее, состояния были переупорядочены в алфавитном порядке, хотя в исходном DataFrame состояния были классифицированы как категориальные и отсортированы в порядке списка, представленном выше. – marshackVB

0

Я укусил подобную проблему, я отправлю образец решения. Вы можете использовать фиктивную переменную и группу.

import pandas as pd 
import numpy as np 

index = pd.MultiIndex.from_tuples(zip(['a', 'a', 'a', 'b', 'b', 'b'], 
             [0, 0, 0, 1, 1, 1], 
             ['x', 'xx', 'xxx', 'x', 'xx', 'xxx']), 
             names=['A', 'B', 'C']) 
df = pd.DataFrame(np.random.rand(6, 3), index = index) 
>>> df 
       0   1   2 
A B C         
a 0 x 0.839870 0.763803 0.847632 
    xx 0.619066 0.715492 0.467518 
    xxx 0.917468 0.923521 0.278665 
b 1 x 0.660889 0.209247 0.502107 
    xx 0.069925 0.889308 0.836755 
    xxx 0.967187 0.650482 0.138759 



desired_order = ['xxx', 'xx', 'x'] 
df = df.reset_index(2) 
mapping = { _ : desired_order.index(_) for _ in df['C'] } 

df['Dummy'] = df['C'].map(lambda x: mapping[x]) #gives desired order 
df = df.groupby(level=['A', 'B']).apply(lambda x: x.sort('Dummy')) 
df.drop('Dummy', axis=1) 


>>> df 
     C   0   1   2 
A B         
a 0 xxx 0.273731 0.561262 0.970034 
    0 xx 0.859063 0.459765 0.921475 
    0 x 0.640554 0.045410 0.512320 
b 1 xxx 0.678473 0.380712 0.252676 
    1 xx 0.501426 0.577250 0.317702 
    1 x 0.586227 0.927453 0.794912 

Там может быть лучше, используя категориальные переменные, введенные в панд 0.15, но я не знаю более простое решение.

+0

Спасибо; Я попробую. – marshackVB

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