2017-07-07 4 views
4

ich einen Pandas Datenrahmen wie diese:Pandas: Trans Paare von Spalten an Zellen

ts | thing_0 | qty_0 | thing_1 | qty_1 | thing_2 | qty_2 
-------------------------------------------------------- 
1 | dog  |  5 | cat  |  3 | mouse |  1 
2 | house |  6 | dog  |  4 | cat  |  2 
... 

Ich möchte dies in einer Art und Weise verändern, dass die thing s Spalten werden und die qty s werden die Zellenwerte. Wie folgt aus:

ts | dog | cat | mouse | house 
------------------------------ 
1 | 5 | 3 |  1 |  0 
2 | 4 | 2 |  0 |  6 
... 

Derzeit mache ich diese Transformation manuell durch manuell über den df.values Array iterieren, aber das ist sehr langsam. Gibt es einen schnelleren Weg, dies mit Pandas umzusetzen?

Ich habe df.pivot gesehen, konnte aber keine Möglichkeit finden, die Beziehung zwischen thing_0 und qty_0 zu beschreiben.

Antwort

3

Sie können str.splitMultiIndex von Spalten erstellen und neu zu gestalten dann durch stack und unstack:

df = df.set_index('ts') 
df.columns = df.columns.str.split('_', expand=True) 
df = df.stack().reset_index(level=1, drop=True) 
     .set_index('thing', append=True)['qty'].unstack(fill_value=0) 
print (df) 
thing cat dog house mouse 
ts       
1  3 5  0  1 
2  2 4  6  0 

Eine andere Lösung mit pivot statt unstack:

df = df.set_index('ts') 
df.columns = df.columns.str.split('_', expand=True) 
df = df.stack().reset_index() 
df = df.pivot(index='ts', columns='thing', values='qty').fillna(0).astype(int) 
print (df) 
thing cat dog house mouse 
ts       
1  3 5  0  1 
2  2 4  6  0 

und dritte Lösung - dynamisch erstellen dict für lreshape und dann unstack:

verwenden

Hinweis - Spalten sortiert werden, wenn nicht df = df.sort_index(axis=1)

t = [x for x in df.columns if x.startswith('thing')] 
q = [x for x in df.columns if x.startswith('qty')] 
df = pd.lreshape(df, {'thing':t, 'qty':q}) 
     .set_index(['ts','thing'])['qty'].unstack(fill_value=0) 

print (df) 
thing cat dog house mouse 
ts       
1  3 5  0  1 
2  2 4  6  0 

EDIT hinzufügen:

lreshape ist jetzt nicht dokumentiert, aber es ist möglich, in Zukunft werden entfernt (with pd.wide_to_long too).

Mögliche Lösung ist die Zusammenführung aller 3 Funktionen zu einem - vielleicht melt, aber jetzt ist es nicht implementiert. Vielleicht in einer neuen Version von Pandas. Dann wird meine Antwort aktualisiert.

4

Sie könnten lreshape verwenden, um die thing und qty Spalten zu vereinigen:

import pandas as pd 

df = pd.DataFrame({'qty_0': [5, 6], 'qty_1': [3, 4], 'qty_2': [1, 2], 'thing_0': ['dog', 'house'], 'thing_1': ['cat', 'dog'], 'thing_2': ['mouse', 'cat'], 'ts': [1, 2]}) 

reshaped = pd.lreshape(df, {'thing':['thing_0','thing_1','thing_2',], 
          'qty':['qty_0','qty_1','qty_2']}) 

result = reshaped.pivot(index='ts', columns='thing', values='qty') 
print(result) 

Ausbeuten

thing cat dog house mouse 
ts       
1  3.0 5.0 0.0 1.0 
2  2.0 4.0 6.0 0.0 

:

In [10]: pd.lreshape(df, {'thing':['thing_0','thing_1','thing_2',], 'qty':['qty_0','qty_1','qty_2']}) 
Out[10]: 
    ts thing qty 
0 1 dog 5 
1 2 house 6 
2 1 cat 3 
3 2 dog 4 
4 1 mouse 1 
5 2 cat 2 

Dann pivot die gewünschte Datenrahmen zu erstellen

Ich denke, jezrael's solution ist besser, da es die Regelmäßigkeit der Spaltennamen nutzt, die Sie zusammenfügen möchten. df.columns.str.split('_', expand=True) ist allgemeiner und weniger repetitiven als

{'thing':['thing_0','thing_1','thing_2',], 
'qty':['qty_0','qty_1','qty_2']} 

lreshape könnte in Situationen nützlich sein, wo die Spaltennamen Sie wollen unregelmäßig sind zu verschmelzen.

Verwandte Themen