2014-12-20 17 views
8

Chciałbym konwertować Pandas DataFrame, która pochodzi z tabeli przestawnej na reprezentację wiersza, jak pokazano poniżej.Spłaszczyć DataFrame z kolumnami z wieloma indeksami

To gdzie jestem:

import pandas as pd 
import numpy as np 
df = pd.DataFrame({ 
    'goods': ['a', 'a', 'b', 'b', 'b'], 
    'stock': [5, 10, 30, 40, 10], 
    'category': ['c1', 'c2', 'c1', 'c2', 'c1'], 
    'date': pd.to_datetime(['2014-01-01', '2014-02-01', '2014-01-06', '2014-02-09', '2014-03-09']) 
}) 
# we don't care about year in this example 
df['month'] = df['date'].map(lambda x: x.month) 
piv = df.pivot_table(["stock"], "month", ["goods", "category"], aggfunc="sum") 
piv = piv.reindex(np.arange(piv.index[0], piv.index[-1] + 1)) 
piv = piv.ffill(axis=0) 
piv = piv.fillna(0) 
print piv 

co skutkuje

stock    
goods  a  b  
category c1 c2 c1 c2 
month      
1   5 0 30 0 
2   5 10 30 40 
3   5 10 10 40 

I to jest, gdy chcę się tam dostać.

goods category month stock 
    a  c1  1  5 
    a  c1  2  0 
    a  c1  3  0 
    a  c2  1  0 
    a  c2  2 10 
    a  c2  3  0 
    b  c1  1 30 
    b  c1  2  0 
    b  c1  3 10 
    b  c2  1  0 
    b  c2  2 40 
    b  c2  3  0 

Previously, użyłem

piv = piv.stack() 
piv = piv.reset_index() 
print piv 

pozbyć multi-indeksów, ale skutkuje to tym, bo obraca się teraz na dwóch kolumnach (["goods", "category"]):

 month category stock  
goods     a b 
0   1  c1  5 30 
1   1  c2  0 0 
2   2  c1  5 30 
3   2  c2 10 40 
4   3  c1  5 10 
5   3  c2 10 40 

Czy ktoś wie, jak mogę pozbyć się wielu indeksów w kolumnie i uzyskać wynik w DataFrame przykładowego formatu?

Odpowiedz

6
>>> piv.unstack().reset_index().drop('level_0', axis=1) 
    goods category month 0 
0  a  c1  1 5 
1  a  c1  2 5 
2  a  c1  3 5 
3  a  c2  1 0 
4  a  c2  2 10 
5  a  c2  3 10 
6  b  c1  1 30 
7  b  c1  2 30 
8  b  c1  3 10 
9  b  c2  1 0 
10  b  c2  2 40 
11  b  c2  3 40 

wtedy wszystko, co potrzebne jest, aby zmienić nazwisko kolumny z 0 do stock.

+1

hmmmm, stopić (mój odpowiedź) traci miesiąc z indeksu :( –

+0

Dzięki. Działa to dobrze z moim przykładem.Jednakże nie do końca rozumiem, dlaczego użycie 'stack' wcześniej działało i teraz powinienem użyć' unstack'. – orange

1

Wydaje mi się, że melt (aka unpivot) jest bardzo zbliżony do tego, co chcesz zrobić:

In [11]: pd.melt(piv) 
Out[11]: 
     NaN goods category value 
0 stock  a  c1  5 
1 stock  a  c1  5 
2 stock  a  c1  5 
3 stock  a  c2  0 
4 stock  a  c2  10 
5 stock  a  c2  10 
6 stock  b  c1  30 
7 stock  b  c1  30 
8 stock  b  c1  10 
9 stock  b  c2  0 
10 stock  b  c2  40 
11 stock  b  c2  40 

Jest nieuczciwe kolumna (stock), który pojawia się tutaj, że nagłówek kolumny jest stała w PIV. Gdybyśmy go nie upuścić pierwszy wytop działa OOTB:

In [12]: piv.columns = piv.columns.droplevel(0) 

In [13]: pd.melt(piv) 
Out[13]: 
    goods category value 
0  a  c1  5 
1  a  c1  5 
2  a  c1  5 
3  a  c2  0 
4  a  c2  10 
5  a  c2  10 
6  b  c1  30 
7  b  c1  30 
8  b  c1  10 
9  b  c2  0 
10  b  c2  40 
11  b  c2  40 

Edycja: powyżej faktycznie spada indeks, trzeba zrobić to kolumny reset_index:

In [21]: pd.melt(piv.reset_index(), id_vars=['month'], value_name='stock') 
Out[21]: 
    month goods category stock 
0  1  a  c1  5 
1  2  a  c1  5 
2  3  a  c1  5 
3  1  a  c2  0 
4  2  a  c2  10 
5  3  a  c2  10 
6  1  b  c1  30 
7  2  b  c1  30 
8  3  b  c1  10 
9  1  b  c2  0 
10  2  b  c2  40 
11  3  b  c2  40 
+0

Ciekawa funkcja, ale gdzie kolumna "miesiąc" idź? – orange

+0

@ lub zmień indeks ap gruszki do opuszczenia, pozostawiając tę ​​odpowiedź tutaj, ponieważ może to być przydatne dla niektórych (mam również nadzieję, że mogę to naprawić!). –

+0

Myślisz, że to błąd lub czy jest to zgodne z projektem? – orange

Powiązane problemy