回答編集履歴

1

追記

2023/01/14 12:10

投稿

bsdfan
bsdfan

スコア4520

test CHANGED
@@ -1,3 +1,43 @@
1
+ 質問が変更されて、「誤差が最大となるように」に合わせてみました。
2
+ (INとOUTのペアリングのところ以外は修正前と同じです)
3
+
4
+ 下記は、直前がINでないINと、直後がOUTでないOUTをマッチさせるようにしたものです。
5
+ これで、だいたい最大っぽい感じになると思いますが、もし合わないケースがあれば、ご自身で条件を変えてみてください。
6
+
7
+ ```python
8
+ import pandas as pd
9
+ import numpy as np
10
+
11
+ # df = ...
12
+
13
+ # 日付ソート
14
+ df = df.sort_values(['datetime'])
15
+
16
+ # INとOUTのペアリング
17
+ def pair_number(x):
18
+ valid_in = (x == 'IN') & (x.shift() != 'IN')
19
+ valid_out = (x == 'OUT') & (x.shift(-1) != 'OUT')
20
+ num = np.arange(len(x))
21
+ num_in = np.maximum.accumulate(np.where(valid_in, num, -1))
22
+ return np.where(valid_out, num_in, num)
23
+
24
+ df['key'] = df.groupby(['user', 'service'])['in_out'].transform(pair_number)
25
+
26
+ # ピボット
27
+ df2 = pd.pivot(
28
+ df,
29
+ index=['user', 'service', 'key'],
30
+ columns='in_out',
31
+ values=['No', 'datetime'])
32
+
33
+ # カラム名の整理
34
+ df2.columns = [c2 + '_' + c1 for (c1, c2) in df2.columns]
35
+ df2 = df2.reset_index().drop(columns='key')
36
+
37
+ print(df2)
38
+ ```
39
+
40
+ ### 修正前の回答
1
41
  datetime でソートして、user, service で groupby した上で、
2
42
  in_out に連番をつけて、'OUT'のところは -1 すると、
3
43
  IN → OUT と連続するところだけが同じ数字になります。