2013-08-10 19 views
6

Ho il seguente DataFrame a cui desidero applicare alcuni calcoli di intervalli di date. Voglio selezionare le righe nel riquadro della data in cui la differenza di data tra i campioni per le persone univoche (dalla data di campionamento) è inferiore a 8 settimane e mantenere la riga con la data più vecchia (ossia il primo campione).Applicare la funzione a un dataframe MultiIndex con panda/python

Ecco un set di dati di esempio. Il set di dati effettivo può superare i 200.000 record.

labno name sex dob   id  location sample_date 
1  John A M 12/07/1969 12345 A   12/05/2112 
2  John B M 10/01/1964 54321 B   6/12/2010 
3  James M 30/08/1958 87878 A   30/04/2012 
4  James M 30/08/1958 45454 B   29/04/2012 
5  Peter M 12/05/1935 33322 C   15/07/2011 
6  John A M 12/07/1969 12345 A   14/05/2012 
7  Peter M 12/05/1935 33322 A   23/03/2011 
8  Jack M 5/12/1921 65655 B   15/08/2011 
9  Jill F 6/08/1986 65459 A   16/02/2012 
10  Julie F 4/03/1992 41211 C   15/09/2011 
11  Angela F 1/10/1977 12345 A   23/10/2006 
12  Mark A M 1/06/1955 56465 C   4/04/2011 
13  Mark A M 1/06/1955 45456 C   3/04/2011 
14  Mark B M 9/12/1984 55544 A   13/09/2012 
15  Mark B M 9/12/1984 55544 A   1/01/2012 

Le persone univoche sono quelle con lo stesso nome e dob. Ad esempio, John A, James, Mark A e Mark B sono persone uniche. Mark A ha tuttavia diversi valori di identificazione.

Normalmente utilizzo R per la procedura e genera un elenco di dataset basato sulla combinazione nome/dob e ordina ogni dataframe in base a data_sempio. Quindi utilizzerei una funzione apply list per determinare se la differenza di data tra il pugno e l'ultimo indice all'interno di ogni dataframe restituisse il più vecchio se fosse meno di 8 settimane dalla data più recente. Ci vuole per sempre.

Vorrei dare qualche suggerimento su come potrei provare con Python/Panda. Ho iniziato creando un MultiIndex con nome/dob/id. La struttura assomiglia a quello che voglio. Quello che devo fare è provare ad applicare alcune delle funzioni che uso in R per selezionare le righe che mi servono. Ho provato a selezionare con df.xs() ma non sto andando molto lontano.

Ecco un dizionario dei dati che possono essere caricati facilmente in panda (anche se con un ordine di colonne diverso).

{ 'dob': {0: '12/07/1969' , 1: '10/01/1964' , 2: '30/08/1958' , 3: '30/08/1958 ', 4: '12/05/1935', 5: '12/07/1969 ', 6: '12/05/1935', 7: '5/12/1921', 8: '6/08/1986 ", 9:" 4/03/1992 ", 10:" 1/10/1977 ", 11:" 1/06/1955 ", 12:" 1/06/1955 ", 13:" 9/12/1984 ', 14: ' 9/12/1984 '},' id ': {0: 12345, 1: 54321, 2: 87878, 3: 45454,
4: 33322, 5: 12345, 6: 33322, 7: 65655, 8: 65459, 9: 41211, 10: 12345, 11: 56465, 12: 45456, 13: 55544, 14: 55544}, "labno": {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10, 10: 11, 11: 12, 12: 13, 13: 14, 14 : 15}, "posizione": {0: 'A', 1: 'B', 2: 'A', 3: 'B', 4: 'C', 5: 'A', 6: 'A', 7 : 'B', 8: 'A', 9: 'C', 10: 'A', 11: 'C', 12: 'C', 13: 'A', 14: 'A'}, ' name ': {0:' John A ', 1:' John B ', 2: ' James ', 3:' James ', 4:' Peter ', 5:' John A ', 6:' Peter ', 7: 'Jack', 8: 'Jill', 9: 'Julie', 10: 'Angela', 11: 'Mark A',
12: 'Mark A', 13: 'Mark B', 14: "Mark B"}, "sample_date": {0: '12/05/2112 ', 1:' 6/12/2010 ', 2: '30/04/2012', 3: '29/04/2012 ', 4: '15/07/2011', 5: '14/05/2012 ', 6: '23/03/2011', 7: '15/08/2011 ', 8: '16/02/2012 ', 9: '15/09/2011', 10: '23/10/2006 ', 11:' 04/04/2011 ', 12:' 3/04/2011 ', 13: '13/09/2012 ", 14:" 1/01/2012 "}," sesso " : {0: 'M', 1: 'M', 2: 'M', 3: 'M', 4: 'M', 5: 'M', 6: 'M', 7: 'M' , 8: 'F', 9: 'F',
10: 'F', 11: 'M', 12: 'M', 13: 'M', 14: 'M'}}

+0

Diciamo che c'erano sei campioni per Mark A. I primi tre sono separati da sei settimane, poi c'è un intervallo di quattro mesi, e poi i secondi tre sono anche separati da sei settimane. Quali righe vorresti mantenere? (IOW, non sono sicuro dello scopo della "differenza di data tra i campioni".) – DSM

+0

Good point @DSM. Se la differenza di data tra il campione più recente più recente impostato per Mark A è più di 8 settimane, vorrei considerare l'altro set Mark A come un nuovo set di campioni. IOW se la differenza di data tra due campioni> 8 settimane considera ciascun set di campioni in modo indipendente. – John

risposta

6

Penso che quello che si potrebbe essere alla ricerca di è

def differ(df): 
    delta = df.sample_date.diff().abs() # only care about magnitude 
    cond = delta.notnull() & (delta < np.timedelta64(8, 'W')) 
    return df[cond].max() 

delta = df.groupby(['dob', 'name']).apply(differ) 

a seconda se si desidera mantenere le persone che non hanno più di 1 campione è possibile chiamare delta.dropna(how='all') per rimuoverli.

Nota che credo avrete bisogno numpy >= 1.7 per il confronto timedelta64 per funzionare correttamente, in quanto vi sono tutta una serie di problemi con timedelta64/datetime64 per numpy < 1.7.

Problemi correlati