Come calcolare la lunghezza totale del processo fino a quando non cambia utilizzando due colonne in Python?

Aug 24 2020

Ecco uno snippet di data-frame che assomiglia a questo (il data frame originale contiene 8k righe):

     User   State      change_datetime  endstate
0  100234     XIM  2016-01-19 17:03:12  Inactive
1  100234  Active  2016-01-28 17:17:15       XIM
2  100234  Active  2016-02-16 17:57:50       NaN
3  100234    Live  2016-02-16 17:58:51    Active
4  213421     XIM  2016-02-16 17:57:53       NaN
5  213421  Active  2018-02-01 10:01:51       XIM
6  213421  Active  2018-02-01 20:49:41       NaN
7  213421  Active  2018-02-13 20:40:11       NaN
8  213421       R  2018-03-04 05:38:51    Active
9  612312    B-98  2018-11-01 17:12:11       XIM

Sto cercando di scoprire quanto tempo ogni Utente unico trascorre in uno stato "Attivo" fino a quando non passa a uno stato diverso da "Attivo". C'è una colonna "stato finale" che contiene un valore "Attivo", quindi volevo calcolare la differenza di tempo totale da quando la colonna "Stato" inizia come "Attivo" fino a quando la colonna "Stato finale" contiene "Attivo"

In origine, ho utilizzato il seguente codice:

df["change_datetime"] = pd.to_datetime(df["change_datetime"])

cond1 = df["State"].eq("Active")
cond2 = df["State"].shift(-1).ne("Active")

start = df.loc[cond1].groupby("User")["change_datetime"].first()
end = df.loc[cond1&cond2].groupby("User")["change_datetime"].first()

print (end-start)
Active_state_duration = (end-start).to_frame()
Active_state_duration.head()

I risultati restituiti sono:

User
100234   19 days 00:40:35
213421   12 days 10:38:20
Name: change_datetime, dtype: timedelta64[ns]

Per l'utente 100234, vengono calcolati 19 giorni e 00:40:35 per la riga 2 e 3, tuttavia dovrebbero essere 19 giorni e 00:41:36 (utilizzando la riga 4) poiché l'utente impiega 1 minuto e 1 secondo per passare da " Attivo "a" Live ".

Speravo di utilizzare la colonna "endstate" in questo codice in modo che la durata del tempo in cui l'utente è "Active" venga eseguita utilizzando la colonna "State" fino a quando la riga di codice successiva ha "Active" come valore in "end_state" e un valore diverso da "Attivo" per "Stato". Ecco un esempio di come spero di calcolare la durata:

C'è un modo per fare questo?

Ecco come cerco di calcolare la durata:

Risposte

2 ShubhamSharma Aug 24 2020 at 11:11

Utilizzare Series.eqper creare una maschera booleana, mquindi filtrare il dataframe utilizzando questa maschera e utilizzare DataFrame.groupbye aggla colonna change_datetimeutilizzando np.ptp:

m = df['State'].eq('Active') | df['endstate'].eq('Active')
s = df[m].groupby(['User', (~m).cumsum()])['change_datetime'].agg(np.ptp).droplevel(1)

OPPURE, se è sempre necessario considerare una transizione per utente nel dataframe:

m1 = df['State'].eq('Active')
m2 = ~m1 & df['endstate'].eq('Active')

s1 = df[m1].groupby('User')['change_datetime'].first()
s2 = df[m2].groupby('User')['change_datetime'].first()

s = s2.sub(s1)

Risultato:

print(s)
User
100234   19 days 00:41:36
213421   30 days 19:37:00
Name: change_datetime, dtype: timedelta64[ns]