2015-03-30 9 views
5

Ich habe einen Datenrahmen von Personen, die jeweils mehrere Datensätze haben. Ich möchte den Datensatz in der Sequenz für jedes Individuum in Python aufzählen. Im Wesentlichen würde Ich mag die ‚Sequenz‘ Spalte in der folgenden Tabelle erstellen:Fügen Sie eine Sequenznummer zu jedem Element in einer Gruppe mit Python

patient date  sequence 
145  20Jun2009  1 
145  24Jun2009  2 
145  15Jul2009  3 
582  09Feb2008  1 
582  21Feb2008  2 
987  14Mar2010  1 
987  02May2010  2 
987  12May2010  3 

Dies ist im Wesentlichen der gleiche Frage wie here, aber ich arbeite in Python und nicht in der Lage die SQL-Lösung zu implementieren. Ich vermute, dass ich eine groupby-Anweisung mit einer iterierbaren Zählung verwenden kann, die bisher jedoch nicht erfolgreich war. Vielen Dank!

Antwort

0

Die Frage ist, wie sortiere ich auf mehreren Spalten von Daten.

Ein einfacher Trick besteht darin, den key Parameter zu der sorted Funktion zu verwenden.

Sie sortieren nach einer Zeichenfolge, die aus den Spalten des Arrays besteht.

rows = ...# your source data 

def date_to_sortable_string(date): 
    # use datetime package to convert string to sortable date. 
    pass 

# Assume x[0] === patient_id and x[1] === encounter date 

# Sort by patient_id and date 
rows_sorted = sorted(rows, key=lambda x: "%0.5d-%s" % (x[0], date_to_sortable_string(x[1]))) 

for row in rows_sorted: 
    print row 
17

Ich stolperte über die Antwort, die peinlich einfach war. Die groupby-Anweisung hat die Option 'cumcount()', die Gruppenelemente aufzählt.

df['sequence']=df.groupby('patient').cumcount() 

Der Vorbehalt ist, dass die Datensätze in der Reihenfolge, die Sie sie aufgezählt werden sollen, sein müssen.

+0

die richtige Antwort :) –

+0

Wow, was für ein Lebensretter - das unendlich läuft schneller als jeder meiner Hacks dafür – Owen

1

Zunächst möchten Sie die Datumsspalte konvertieren eine Pandas Datetime zu sein (statt Strings):

In [11]: pd.to_datetime(df['date'], format='%d%b%Y') 
Out[11]: 
0 2009-06-20 
1 2009-06-24 
2 2009-07-15 
3 2008-02-09 
4 2008-02-21 
5 2010-03-14 
6 2010-05-02 
7 2010-05-12 
Name: date, dtype: datetime64[ns] 

Hinweis: docs für mögliche Format-Optionen.

In [12]: df['date'] = pd.to_datetime(df['date'], format='%d%b%Y') 

In [13]: df 
Out[13]: 
    patient  date sequence 
0  145 2009-06-20   1 
1  145 2009-06-24   2 
2  145 2009-07-15   3 
3  582 2008-02-09   1 
4  582 2008-02-21   2 
5  987 2010-03-14   1 
6  987 2010-05-02   2 
7  987 2010-05-12   3 

Ist dies nicht in chronologischer Reihenfolge ist (für jeden Patienten), würde ich es zuerst sortieren:

In [14]: df = df.sort('date') 

Jetzt können Sie GROUPBY und cumcount:

In [15]: g = df.groupby('patient') 

In [16]: g.cumcount() + 1 
Out[16]: 
2 1 
3 2 
0 1 
1 2 
4 1 
5 2 
6 3 
dtype: int64 

Welche ist was Sie wollen (obwohl es nicht in Ordnung ist):

In [17]: df['sequence'] = g.cumcount() + 1 

In [18]: df 
Out[18]: 
     patient  date sequence 
2  582 2008-02-09   1 
3  582 2008-02-21   2 
0  145 2009-06-24   1 
1  145 2009-07-15   2 
4  987 2010-03-14   1 
5  987 2010-05-02   2 
6  987 2010-05-12   3 

neu anordnen (obwohl Sie nicht brauchen können) verwenden sort_index (oder wir könnten indizieren, wenn wir die ursprünglichen Datenrahmen-Index gespeichert): *

In [19]: df.sort_index() 
Out[19]: 
    patient  date sequence 
0  145 2009-06-24   1 
1  145 2009-07-15   2 
2  582 2008-02-09   1 
3  582 2008-02-21   2 
4  987 2010-03-14   1 
5  987 2010-05-02   2 
6  987 2010-05-12   3 
Verwandte Themen