2016-05-24 19 views
3

Ich habe eine Tabelle in einer Kreuztabelle Format, zB unter:Gibt es eine Möglichkeit, die Melt-Funktion in Python für mehrere Spalten zu verwenden?

State Item # x1 x2 x3 y1 y2 y3 z1 z2 z3 
CA  1  6 4 3 7 5 3  11  5  1 
CA  2  7 3 1 15 10 5  4  2  1 
FL  3  3 2 1 5 3 2  13  7  2 
FL  4  9 4 2 16 14 12  14  5  4 

Ich versuche, die Schmelze Funktion zu verwenden, um die Daten in folgendem Format zu setzen:

State Item # x xvalue y yvalue z zvalue 
CA  1  x1 6  y1 7  z1 11 
CA  1  x2 4  y2 5  z2 5 
CA  1  x3 3  y3 3  z3 1 
CA  2  x1 7  y1 15 z1 4 
CA  2  x2 3  y2 10 z2 2 
CA  2  x3 1  y3 5  z3 1  

Ich weiß, wie man die Schmelzfunktion für nur einen der Werte verwendet, sagen wir x. Aber ich weiß auch nicht, wie ich das mit y und z machen soll. Siehe meinen Code unten, um es nur für x zu tun. Gibt es eine Möglichkeit das ich das auch für y und z einstellen kann? Oder sollte ich versuchen, separate Schmelzfunktionen für x, y und z zu haben und sie dann irgendwie zu kombinieren?

df_m = pd.melt(df, id_vars=['State', 'Item #'], 
      value_vars=['x1','x2','x3'], 
      var_name='x', value_name='xvalue') 
+0

Ich denke, Sie müssen mehrere Schmelzen tun. – BrenBarn

Antwort

1

Ich glaube nicht, aber man konnte zwei Line-Lösung verwenden:

values = [['x1','x2','x3'], ['y1', 'y2', 'y3'], ['z1', 'z2', 'z3']] 

df_m = pd.concat([pd.melt(df, id_vars=['State', 'Item_#'], value_vars=val, var_name='var', value_name='value') for val in values]) 

Die pd.concat Funktion ein leistungsfähiger (das heißt schnell) Weg ist, Datenrahmen vertikal zu stapeln.

1

Hier ist eine Version, die melt nicht verwendet, aber für eine beliebige Anzahl von xyz 'Gruppen' funktioniert.

import pandas as pd 
from io import StringIO 

df = pd.read_csv(StringIO(''' 
    State ItemN x1 x2 x3 y1 y2 y3 z1 z2 z3 
CA  1  6 4 3 7 5 3  11  5  1 
CA  2  7 3 1 15 10 5  4  2  1 
FL  3  3 2 1 5 3 2  13  7  2 
FL  4  9 4 2 16 14 12  14  5  4'''), 
sep=r' +') 

# prepare index 
df = df.set_index(list(df.columns[:2])) 
df.columns = pd.MultiIndex.from_tuples([(c[0], c) for c in df.columns]) 

#    x   y   z  
#    x1 x2 x3 y1 y2 y3 z1 z2 z3 
# State ItemN        
# CA 1  6 4 3 7 5 3 11 5 1 
#  2  7 3 1 15 10 5 4 2 1 
# FL 3  3 2 1 5 3 2 13 7 2 
#  4  9 4 2 16 14 12 14 5 4 


# stack and concat each 'group' 
df2 = pd.concat((
    df[c].stack().reset_index(-1) 
    for c in df.columns.levels[0]), 
    axis=1) 

# rename the columns 
new_cols = [None for _ in range(df2.shape[1])] 
new_cols[::2] = [c for c in df.columns.levels[0]] 
new_cols[1::2] = [c + 'value' for c in df.columns.levels[0]] 

df2.columns = new_cols 

#    x xvalue y yvalue z zvalue 
# State ItemN          
# CA 1  x1  6 y1  7 z1  11 
#  1  x2  4 y2  5 z2  5 
#  1  x3  3 y3  3 z3  1 
#  2  x1  7 y1  15 z1  4 
#  2  x2  3 y2  10 z2  2 
#  2  x3  1 y3  5 z3  1 
# FL 3  x1  3 y1  5 z1  13 
#  3  x2  2 y2  3 z2  7 
#  3  x3  1 y3  2 z3  2 
#  4  x1  9 y1  16 z1  14 
#  4  x2  4 y2  14 z2  5 
#  4  x3  2 y3  12 z3  4 
0

Was ist mit pd.wide_to_long?

# Make dataframe 
df = pd.DataFrame({'State' : ['CA']*2 + ['FL']*2, 
        'Item' : [1, 2, 3, 4], 
        'x1' : [6, 7, 3, 9], 
        'x2' : [4, 3, 2, 4], 
        'x3' : [3, 1, 1, 2], 
        'y1' : [7, 15, 5, 16], 
        'y2' : [5, 10, 3, 14], 
        'y3' : [3, 5, 2, 12], 
        'z1' : [11, 4, 13, 14], 
        'z2' : [5, 2, 7, 5], 
        'z3' : [1, 1, 2, 4]}) 

# Make final dataframe using pd.wide_to_long 
final = pd.wide_to_long(df, 
         stubnames = ['x', 'y', 'z'], 
         i = ['State', 
          'Item'], 
         j = 'number').reset_index() 

# Show final dataframe 
final 

wide_to_long

Ich weiß, dass der Datenrahmen zurück Sie nicht genau sehen, wie das angefordert, aber es könnte noch funktionieren. Tatsächlich kombiniert es jetzt Ihre x-, y-, z-, xvalue-, yvalue- und zvalue-Spalten in x, y, z und eine "Zahl" -Spalte, um auf die ersten, zweiten und dritten Werte zu verweisen.

Verwandte Themen