2013-08-15 10 views
19

Ich habe derzeit ein DataFrame wie angelegt:Unpivot Pandas Daten

 Jan Feb Mar Apr ... 
2001 1 12 12 19 
2002 9 ... 
2003 ... 

und ich möchte „Entpivotisierung“ die Daten aussehen:

Date Value 
Jan 2001 1 
Feb 2001 1 
Mar 2001 12 
... 
Jan 2002 9 

Was ist der beste Weg, um zu erreichen, dies mit Pandas/numpy?

Antwort

23

Sie müssen nur df.unstack() tun, und das wird eine MultiIndexed Series mit Monat als erste Ebene und dem Jahr als der zweiten Ebene Index erstellen. Wenn Sie möchten, dass sie Spalten sind, dann rufen Sie einfach reset_index() danach.

>>> df 
     Jan Feb 
2001 3 4 
2002 2 7 
>>> df.unstack() 
Jan 2001 3 
    2002 2 
Feb 2001 4 
    2002 7 
>>> df = df.unstack().reset_index(name='value') 
>>> df 
    level_0 level_1 value 
0  Jan  2001  3 
1  Jan  2002  2 
2  Feb  2001  4 
3  Feb  2002  7 
>>> df.rename(columns={'level_0': 'month', 'level_1': 'year'}, inplace=True) 
>>> df 
    month year value 
0 Jan 2001  3 
1 Jan 2002  2 
2 Feb 2001  4 
3 Feb 2002  7 
6

Eine andere Lösung wäre pandas.melt zu verwenden unnötige Schaffung eines MultiIndex zu vermeiden, obwohl dies nicht dass teuer ist, wenn Ihr Rahmen ist klein und mit meiner Lösung, die Sie noch eine temporäre für die "erstellen müssen geschmolzene "Daten. Die Eingeweide melt legen nahe, dass beide id_vars und value kopiert seit id_vars Erstellung verwendet tile und value Schöpfung nutzt df.values.ravel('F') die ich glaube, eine Kopie macht, wenn Ihre Daten nicht in Fortran um sind.

EDIT: Ich bin nicht ganz sicher, wenn eine Kopie erstellt wird, wenn ravel erst seit den order Parametern aufgerufen wird gibt an, wie Sie Ihre Daten wollen lesen und die docstring sagt eine Kopie nur gemacht, wenn nötig.

In [99]: mons 
Out[99]: 
['Jan', 
'Feb', 
'Mar', 
'Apr', 
'May', 
'Jun', 
'Jul', 
'Aug', 
'Sep', 
'Oct', 
'Nov', 
'Dec'] 

In [100]: df = DataFrame(randn(201, len(mons)), columns=mons, index=map(str, arange(1901, 2102))) 

In [101]: df.head() 
Out[101]: 
     Jan Feb Mar Apr May Jun Jul Aug Sep Oct \ 
1901 1.141 -0.270 0.329 0.214 -1.030 0.324 -1.448 2.003 -0.061 0.477 
1902 0.136 0.151 0.447 -0.493 1.329 1.410 0.020 -0.705 0.870 0.478 
1903 -0.000 0.689 1.768 -0.057 -1.471 0.515 -0.315 0.703 2.511 0.592 
1904 1.199 1.246 -0.255 0.182 -0.454 -0.452 1.074 0.178 2.495 -0.543 
1905 1.073 1.375 -1.837 1.048 -0.139 -0.273 -0.958 -1.164 -1.012 0.950 

     Nov Dec 
1901 0.102 0.122 
1902 2.941 0.654 
1903 0.347 -1.636 
1904 -0.047 0.457 
1905 1.277 -0.284 

In [102]: df.reset_index(inplace=True) 

In [103]: df.head() 
Out[103]: 
    index Jan Feb Mar Apr May Jun Jul Aug Sep Oct \ 
0 1901 1.141 -0.270 0.329 0.214 -1.030 0.324 -1.448 2.003 -0.061 0.477 
1 1902 0.136 0.151 0.447 -0.493 1.329 1.410 0.020 -0.705 0.870 0.478 
2 1903 -0.000 0.689 1.768 -0.057 -1.471 0.515 -0.315 0.703 2.511 0.592 
3 1904 1.199 1.246 -0.255 0.182 -0.454 -0.452 1.074 0.178 2.495 -0.543 
4 1905 1.073 1.375 -1.837 1.048 -0.139 -0.273 -0.958 -1.164 -1.012 0.950 

    Nov Dec 
0 0.102 0.122 
1 2.941 0.654 
2 0.347 -1.636 
3 -0.047 0.457 
4 1.277 -0.284 

In [104]: res = pd.melt(df, id_vars=['index'], var_name=['months']) 

In [105]: res['date'] = res['months'] + ' ' + res['index'] 

In [106]: res.head() 
Out[106]: 
    index months value  date 
0 1901 Jan 1.141 Jan 1901 
1 1902 Jan 0.136 Jan 1902 
2 1903 Jan -0.000 Jan 1903 
3 1904 Jan 1.199 Jan 1904 
4 1905 Jan 1.073 Jan 1905 
+0

Würde die down-Wähler kümmern sich zu kommentieren? –

+0

Ah ich sehe. Ja, "besser" war eine schlechte Wortwahl. –