Pythonの2つの列を使用して、プロセスが変化するまでのプロセスの全長を計算するにはどうすればよいですか?

Aug 24 2020

これは次のようなデータフレームのスニペットです(元のデータフレームには8k行が含まれています)。

     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

それぞれの一意のユーザーが「アクティブ」以外の別の状態に変わるまで、「アクティブ」状態で費やす時間を調べようとしています。「Active」値を含む「endstate」列があるので、「State」列が「Active」として開始されてから「endstate」列に「Active」が含まれるまでの合計時間差を計算したかったのです。

元々、私は次のコードを使用していました。

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

返される結果は次のとおりです。

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

ユーザー100234の場合、2行目と3行目で19日と00:40:35が計算されますが、ユーザーが 'から移行するのに1分1秒かかるため、19日と00:41:36(4行目を使用)である必要があります。 「アクティブ」から「ライブ」。

このコードで「endstate」列を使用して、「Active」であるユーザーの期間が「State」列を使用して実行され、次のコード行で「end_state」の値が「Active」になるようにしたいと考えていました。 「状態」の「アクティブ」以外の別の値。期間を計算する方法の例を次に示します。

これを行う方法はありますか?

これが私が期間を計算しようとしている方法です:

回答

2 ShubhamSharma Aug 24 2020 at 11:11

を使用Series.eqしてブールマスクを作成し、mこのマスクを使用してデータフレームをフィルタリングし、次を使用DataFrame.groupbyしaggて列change_datetimeを使用し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)

または、データフレーム内のユーザーごとに1つの遷移を常に考慮する必要がある場合:

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)

結果:

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