2016-03-21 11 views
1

Ich versuche Python/Pandas zu lernen und habe, was ich glaube, ein ziemlich grundlegendes Problem.Pandas Datenframe: nach Auftrag in Untergruppe entstapeln, nicht nach Wert

Ich habe Daten von der folgenden Form:

 
id X 
1 1 
1 2 
2 2 
2 3 
3 4 
3 5 
3 5 
3 3 
3 3 
3 4 
4 3 
4 4 
4 6 

ich die Daten von etwas ähnlich einem unstack Format umwandeln wollen: Ich gruppieren möchten durch die id, sortieren Sie die X Werte, legen Sie die erste X -Wert in x1, der zweite X -Wert in x2, usw. Der Datensatz ist ziemlich groß (mehr als 1Millon "Zeilen"). Die meisten Werte in X sind eindeutig (daher möchte ich nicht den Wert von X als Spaltenname verwenden, sondern den Auftrag von X). Nachdem ich mag ich fertig bin würde mit einem Datenrahmen, die wie dies am Ende:

 
id x1 x2 x3 
1 1 2 nan 
2 2 3 nan 
3 3 4 5 
4 3 4 6 
+0

„über blutig Zeit!" ist ein wenig ungnädig, aber ich dachte, es würde viel zu weit gehen, um es zu bearbeiten. –

+0

Aus der Diskussion unten meine Antwort, ich muss jetzt vorschlagen, dass dies unklar ist. –

+0

Punkt genommen. Ich entschuldige mich für die "über die blutige Zeit!" und entfernte es von der Frage. –

Antwort

0

IIUC, könnten Sie so etwas wie

>>> df = df.drop_duplicates() 
>>> df = df.sort_values(["id", "X"]) 
>>> df["xcol"] = "x" + (df.groupby("id")["X"].rank().astype(int)).astype(str) 
>>> df = df.pivot(index="id", columns="xcol", values="X") 
>>> df 
xcol x1 x2 x3 
id    
1  1 2 NaN 
2  2 3 NaN 
3  3 4 5 
4  3 4 6 

Schritt-für-Schritt tun, zuerst wir können die Duplikate und sortieren entfernen:

>>> df = df.drop_duplicates() 
>>> df = df.sort_values(["id", "X"]) 
>>> df 
    X id 
0 1 1 
1 2 1 
2 2 2 
3 3 2 
7 3 3 
4 4 3 
5 5 3 
10 3 4 
11 4 4 
12 6 4 

Dann können wir die Elemente in einem groupby Rang, und bauen die entsprechenden Werte, die wir in der Spalte verwenden werden (cumcount hätte auch hier) gearbeitet:

>>> df["xcol"] = "x" + (df.groupby("id")["X"].rank().astype(int)).astype(str) 
>>> df 
    X id xcol 
0 1 1 x1 
1 2 1 x2 
2 2 2 x1 
3 3 2 x2 
7 3 3 x1 
4 4 3 x2 
5 5 3 x3 
10 3 4 x1 
11 4 4 x2 
12 6 4 x3 

und schließlich schwenken wir:

>>> df = df.pivot(index="id", columns="xcol", values="X") 
>>> df 
xcol x1 x2 x3 
id    
1  1 2 NaN 
2  2 3 NaN 
3  3 4 5 
4  3 4 6 

Wir konnten genau Ihre beschriebenen Ausgabeformat erhalten, wenn Sie darauf bestanden:

>>> df.columns.name = None 
>>> df.reset_index() 
    id x1 x2 x3 
0 1 1 2 NaN 
1 2 2 3 NaN 
2 3 3 4 5 
3 4 3 4 6 
+0

Danke für eine tolle Antwort! Ein paar Dinge über die ich mich wundere: Erstens, der astype (int) wird nicht funktionieren, da es manchmal NANs in den Daten gibt. Ich benutze stattdessen ein float, aber dann werden die neuen Spalte Names x1.0 x2.0 etc, nicht x1, x2. Gibt es eine Möglichkeit, das zu "reparieren"? Zweitens werden die Datentypen vom Pivot nicht beibehalten. Es ist in Text umgewandelt worden, aber in Wirklichkeit ist es oft Datum, Floats oder Ints. Wie könnte ich das "reparieren"? Danke noch einmal! –