Aquí están las dos series. Se generaron después de agrupar un marco de datos basado en dos valores de columna, patient_id y event_description:

Serie 1:

patient_id                                event_description     
A                                             DiagnosisA          2016-09-15
B                                             DiagnosisA          2013-01-01
C                                             DiagnosisA         2016-01-10
D                                             DiagnosisA          2015-01-02

Serie 2:

patient_id                                 event_description     
A                                             DiagnosisB          2016-09-30
B                                             DiagnosisB          2013-01-04
D                                             DiagnosisB          2015-01-15

Así que esencialmente me gustaría encontrar la diferencia de tiempo entre cada paciente. Por ejemplo, para el paciente A volvería 15 días, pero para el paciente C, podría decir `NaN.

1
madsthaks 30 oct. 2017 a las 07:26

3 respuestas

La mejor respuesta

Suponiendo que groupby incluye tanto DiagnosisB como DiagnosisA, puede unstack de antemano y restar

# This should be what you have after groupby
s = pd.concat([s1, s2])

s

patient_id  event_description
A           DiagnosisA          2016-09-15
B           DiagnosisA          2013-01-01
C           DiagnosisA          2016-01-10
D           DiagnosisA          2015-01-02
A           DiagnosisB          2016-09-30
B           DiagnosisB          2013-01-04
D           DiagnosisB          2015-01-15
Name: Date, dtype: datetime64[ns]

Entonces puedes unstack y restar

s.unstack().pipe(lambda d: d.DiagnosisB - d.DiagnosisA)

patient_id
A   15 days
B    3 days
C       NaT
D   13 days
dtype: timedelta64[ns]

No recomendado
Pero divertido con unstack y squeeze

s1.unstack().squeeze().rsub(s2.unstack().squeeze())

patient_id
A   15 days
B    3 days
C       NaT
D   13 days
dtype: timedelta64[ns]

También no recomendado
Pero divertido con xs

s1.xs('DiagnosisA', level=1).rsub(s2.xs('DiagnosisB', level=1))

patient_id
A   15 days
B    3 days
C       NaT
D   13 days
Name: Date, dtype: timedelta64[ns]

No recomendación final
Tenía que mostrar pd.IndexSlice
Nota: los índices deben estar completamente clasificados para que esto funcione.

s1.loc[pd.IndexSlice[:, 'DiagnosisA']].rsub(s2.loc[pd.IndexSlice[:, 'DiagnosisB']])

patient_id
A   15 days
B    3 days
C       NaT
D   13 days
Name: Date, dtype: timedelta64[ns]
3
piRSquared 30 oct. 2017 a las 06:19

Si la columna event_description no tiene ningún papel que jugar aquí, sugeriría simplemente deshacerse de ella. Realice una llamada reset_index y simplemente reste los resultantes.

r1 = df1.reset_index(level=1, drop=1)
r2 = df2.reset_index(level=1, drop=1)

r = r2.sub(r1)

r
           time
patient_id        
A          15 days
B           3 days
C              NaT
D          13 days
3
cs95 30 oct. 2017 a las 06:10

Puede usar reset_index, también podemos usar droplevel es decir

df2.index = df2.index.droplevel(1)
df1.index = df1.index.droplevel(1)

df2 - df1

Salida:

           time
patient_id        
A          15 days
B           3 days
C              NaT
D          13 days
2
Bharath 30 oct. 2017 a las 05:54