2016-05-04 4 views
1

Ich habe einen Datensatz wie folgt aus:Python Pandas: wie Datenrahmen (schnell) auf Basis von Nicht-Null-Säulen wachsen

import pandas as pd 
data = pd.DataFrame({'col1': ['1_xy','2_xy','3_xy','4_xy','5_xy'], 
        'a' : [1,0,1,1,1], 'g' : [1,0,0,1,0], 
        'c' : [1,0,0,0,0], 'd' : [0,1,0,1,0], 
        'e' : [0,1,0,0,0], 'f' : [0,1,0,0,0], 
        'b' : [0,1,0,0,0], 'h' : [0,1,0,0,0], 
        'i' : [0,1,0,0,0], 'j' : [0,0,1,0,0], 
        'k' : [0,0,1,0,0], 'l' : [0,0,0,0,1], 
        'm' : [0,0,0,0,1]}) 

Ausgang:

 col1 a b c d e f g h i j k l m 
    0 1_xy 1 0 1 0 0 0 1 0 0 0 0 0 0 
    1 2_xy 0 1 0 1 1 1 0 1 1 0 0 0 0 
    2 3_xy 1 0 0 0 0 0 0 0 0 1 1 0 0 
    3 4_xy 1 0 0 1 0 0 1 0 0 0 0 0 0 
    4 5_xy 1 0 0 0 0 0 0 0 0 0 0 1 1 

und ich habe einen Code, der iteriert durch alle Werte dieser Datenrahmen, und basierend auf den Säulen mit nicht-Null-Einträge füllen ich einen zweiten Datenrahmen wie folgt aus:

import re 
    df = pd.DataFrame(columns=["col_a", "col_b"]) 
    cols = [name for name in data.columns if not re.search("col1", name)] 
    idx = 0 
    for _, row in data.iterrows(): 
     for name in cols: 
      if row[name]>0: 
       df.loc[idx] = [row[0], name] 
       idx+=1 

Das Ergebnis Folgendes ist:

 col_a col_b 
    0 1_xy a 
    1 1_xy c 
    2 1_xy g 
    3 2_xy b 
    4 2_xy d 
    5 2_xy e 
    6 2_xy f 
    7 2_xy h 
    8 2_xy i 
    9 3_xy a 
    10 3_xy j 
    11 3_xy k 
    12 4_xy a 
    13 4_xy d 
    14 4_xy g 
    15 5_xy a 
    16 5_xy l 
    17 5_xy m 

Nun zu meiner Frage: Hat jemand eine Methode kennt diese ineffiziente Art und Weise meinen zweiten Datenrahmen zur Herstellung zu beschleunigen? Es sollte zumindest eine Möglichkeit geben, zu vermeiden, dass jede Spalte irgendwie mit einem if-test überprüft werden muss. Ich bin wirklich bestrebt, meine Python-Programmierkenntnisse zu verbessern - also bin ich offen für alle möglichen interessanten Lösungen hier. Ich brauche es nur, um meinen aktuellen Benchmark zu schlagen (den ich nicht atm anbiete.)

Vielen Dank im Voraus!

Antwort

2

Ich glaube, Sie können zuerst replace alle 0 Werte NaN, dann set_index aus Spalte col1 und stack. Letzte drop Spalte tmp:

Hinweis: Eine weitere Möglichkeit ist die Verwendung Teilmenge mit mask von data = data[data != 0]

data = data.replace({0: np.nan}) 
#data = data[data != 0] 

df = data.set_index('col1').stack().reset_index() 
df.columns = ['col_a','col_a','tmp'] 
print df.drop('tmp', axis=1) 
    col_a col_a 
0 1_xy  a 
1 1_xy  c 
2 1_xy  g 
3 2_xy  b 
4 2_xy  d 
5 2_xy  e 
6 2_xy  f 
7 2_xy  h 
8 2_xy  i 
9 3_xy  a 
10 3_xy  j 
11 3_xy  k 
12 4_xy  a 
13 4_xy  d 
14 4_xy  g 
15 5_xy  a 
16 5_xy  l 
17 5_xy  m 

Wie MaxU in Kommentar erwähnt, können Sie eine Zeile verwenden:

data[data!=0].set_index('col1') 
      .stack() 
      .reset_index() 
      .drop([0],axis=1) 
      .rename(c‌​olumns={'col1':'col_a','level_1':'col_b'}) 
+1

Einzeiler: ' data [Daten! = 0] .set_index ('col1'). stack(). reset_index(). drop ([0], Achse = 1) .rename (columns = {'col1': 'col_a', 'level_1' : 'col_b'}) ' – MaxU

+0

@MaxU - Danke, ich füge es zur Antwort hinzu. – jezrael

+0

Vielen Dank für die netten Vorschläge (an euch beide). Ich werde Ihre Antwort akzeptieren, nachdem ich einige Laufzeittests für einen großen Datensatz durchgeführt habe. Nochmals vielen Dank. – Magnus

Verwandte Themen