2016-11-02 7 views
1

einen Datenrahmen zu haben wie:Kombinieren Sie Spalten in einem Datenrahmen

import pandas 

df = pandas.DataFrame({'a': [1, 2, 3], 'b': [9, 8, 7], 'c': [4, 5, 6]}) 
df 

enter image description here

ich mit einem Datenrahmen haben möchte:

  • eine Faktor/Kategorie Spalte ['a', 'b']. Der Name dieser Spalte ist mir egal.
  • eine Säule, die den alten Wert der a oder b Spalte hat, auf dem Faktor ['a', 'b'] abhängig. Der Name dieser Spalte ist mir egal.
  • Halten c Spaltenwerte und den Namen (die tatsächliche Datenrahmen hat mehrere Spalten, die ich behalten möchte).
  • ich über die Reihenfolge der Spalten in dem resultierenden Datenrahmen, noch wenn einige (oder überhaupt) von ihnen nicht als Index gesetzt kümmern.

Dies ist ein Beispiel dafür, was Ich mag würde bekommen:

df['name_a'] = 'a' 
df['name_b'] = 'b' 

c0 = pandas.concat([df['name_a'], df['name_b']]) 
c1 = pandas.concat([df['a'], df['b']]) 
c2 = pandas.concat([df['c'], df['c']]) 

newdf = pandas.concat([c0, c1, c2], axis=1) 
newdf 

enter image description here

Gibt es einen besseren Weg, um das gleiche Ergebnis zu erzielen? Ich fühle, dass es sehr hässlich ist. Vielleicht eine pandas Funktion, die ich vermisse und macht den Code viel sauberer und einfach zu verstehen?

Antwort

1

Ich glaube, Sie brauchen melt:

print (pd.melt(df,id_vars='c', var_name='0', value_name='1')) 
    c 0 1 
0 4 a 1 
1 5 a 2 
2 6 a 3 
3 4 b 9 
4 5 b 8 
5 6 b 7 

Eine andere Lösung mit stack mit sort_values:

df1 = df.set_index('c').stack().reset_index().sort_values('level_1') 
df1.columns = ['c', '0','1'] 
print (df1) 
    c 0 1 
0 4 a 1 
2 5 a 2 
4 6 a 3 
1 4 b 9 
3 5 b 8 
5 6 b 7 

Weitere allgemeine Lösung - verwenden list comprehension für Filter alle Spalten, die nicht a und b variabel sind cols :

cols = [col for col in df.columns if col not in ['a','b']] 
print (cols) 
['c'] 

print (pd.melt(df,id_vars=cols, var_name='0', value_name='1')) 
    c 0 1 
0 4 a 1 
1 5 a 2 
2 6 a 3 
3 4 b 9 
4 5 b 8 
5 6 b 7 

Probe mit einer anderen Spalte g hinzugefügt:

df = pd.DataFrame({'a': [1, 2, 3], 
        'b': [9, 8, 7], 
        'c': [4, 5, 6], 
        'g': [0, 1, 7]}) 

print (df) 
    a b c g 
0 1 9 4 0 
1 2 8 5 1 
2 3 7 6 7 

cols = [col for col in df.columns if col not in ['a','b']] 
print (cols) 
['c', 'g'] 

Schnellere Lösung mit numpy.setdiff1d:

cols = np.setdiff1d(df.columns, ['a','b']).tolist() 
print (cols) 
['c', 'g'] 

print (pd.melt(df,id_vars=cols, var_name='0', value_name='1')) 
    c g 0 1 
0 4 0 a 1 
1 5 1 a 2 
2 6 7 a 3 
3 4 0 b 9 
4 5 1 b 8 
5 6 7 b 7 
+0

Danke, das sieht ziemlich gut! Beachten Sie jedoch, dass "* der eigentliche Datenrahmen mehrere Spalten enthält, die ich behalten möchte *" (d. H .: viele 'c' Spalten). Gibt es eine Möglichkeit, dies zu tun, indem Sie 'a' und' b' als Parameter anstelle von 'c' verwenden? ('A' und 'b' ist immer 2, aber es gibt eine Menge von 'c' Spalten mit verschiedenen Namen, und ich möchte sie alle halten). – Peque

+0

sicher, gib mir eine sek. – jezrael

+0

Bitte überprüfen Sie update meine Antwort. – jezrael

Verwandte Themen