Como calcular o comprimento total do processo até que ele mude usando duas colunas em python?

Aug 24 2020

Aqui está um snippet de frame de dados semelhante a este (frame de dados original contém 8k linhas):

     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

Estou tentando descobrir quanto tempo cada usuário único passa em um estado 'Ativo' até que mude para um estado diferente de 'Ativo'. Há uma coluna 'endstate' que contém um valor 'Active', então eu queria calcular a diferença de tempo total de quando a coluna 'State' começa como 'Active' até a coluna 'endstate' contém 'Active'

Originalmente, usei o seguinte código:

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()

Os resultados retornados são:

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

Para o usuário 100234, 19 dias e 00:40:35 são calculados para as linhas 2 e 3, no entanto, deve ser 19 dias e 00:41:36 (usando a linha 4), pois o usuário leva 1 minuto e 1 segundo para fazer a transição ' Ativo 'para' Ao vivo '.

Eu esperava usar a coluna 'endstate' neste código para que o tempo de duração do Usuário sendo 'Ativo' seja executado usando a coluna 'Estado' até que a próxima linha de código tenha 'Ativo' como o valor em 'end_state' e um valor diferente de 'Ativo' para 'Estado'. Aqui está um exemplo de como espero calcular a duração do tempo:

Existe uma maneira de fazer isso?

Aqui está como estou tentando calcular a duração:

Respostas

2 ShubhamSharma Aug 24 2020 at 11:11

Use Series.eqpara criar uma máscara booleana, em mseguida, filtre o dataframe usando esta máscara e use DataFrame.groupbye agga coluna change_datetimeusando 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)

OU, se sempre for necessário considerar uma transição por usuário no 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)

Resultado:

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