2015-03-30 10 views
5

Ho un dataframe di individui che hanno ciascuno più record. Voglio enumerare il record nella sequenza per ogni individuo in python. Essenzialmente Vorrei creare la colonna 'sequenza' nella seguente tabella:Aggiungere un numero di sequenza a ciascun elemento di un gruppo usando 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 

Questo è essenzialmente la stessa domanda di here, ma sto lavorando in pitone e in grado di implementare la soluzione SQL. Sospetto di poter usare una dichiarazione di gruppo con un conteggio iterabile, ma finora non ho avuto successo. Grazie!

risposta

0

La domanda è: come posso ordinare su più colonne di dati.

Un semplice trucco consiste nell'utilizzare il parametro key nella funzione sorted.

L'ordinamento verrà eseguito in base a una stringa creata dalle colonne dell'array.

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

Mi sono imbattuto in una risposta che era imbarazzantemente semplice. L'istruzione groupby ha un'opzione 'cumcount()' che enumera elementi di gruppo.

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

L'avvertenza è che i record devono essere nell'ordine in cui li si desidera elencare.

+0

è la risposta corretta :) –

+0

Wow che un salvagente - che corre all'infinito più veloce di tutti i miei hack per questo – Owen

1

In primo luogo si vuole convertire la colonna della data per essere un datetime panda (piuttosto che le stringhe):

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] 

Nota: vedi docs di possibili opzioni di formato.

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 

Se questo non è in ordine di data (per ogni paziente), che avrebbe risolto prima:

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

Ora è possibile groupby e 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 

Quale è quello che vuoi (anche se è fuori servizio):

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 

Per riorganizzare (anche se si potrebbe non essere necessario) utilizzare sort_index (o potremmo reindex se abbiamo salvato l'indice iniziale di dataframe): *

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