簡體   English   中英

將當前行值與前一行值進行比較

[英]Compare current row value to previous row values

我有來自用戶 A 一天的登錄歷史數據。 我的要求是用戶 A 在任何時候都只能有一個有效的登錄名。 在下面的示例中,用戶可能多次嘗試成功登錄,而他的第一個會話仍處於活動狀態。 因此,在有效會話期間發生的任何登錄都需要標記為重復。

示例 1:

在下面的第一個示例數據中,雖然用戶仍然從00:12:3801:00:02 (index 0)登錄,但用戶在00:55:1401:00:02 (index 1)有另一個登錄01:00:02 (index 1)

同樣,如果我們比較index 23 ,我們可以看到index 3處的記錄是按要求重復登錄。

  start_time  end_time
0   00:12:38  01:00:02
1   00:55:14  01:00:02
2   01:00:02  01:32:40
3   01:00:02  01:08:40
4   01:41:22  03:56:23
5   18:58:26  19:16:49
6   20:12:37  20:52:49
7   20:55:16  22:02:50
8   22:21:24  22:48:50
9   23:11:30  00:00:00

預期輸出:

  start_time  end_time   isDup
0   00:12:38  01:00:02       0
1   00:55:14  01:00:02       1
2   01:00:02  01:32:40       0
3   01:00:02  01:08:40       1
4   01:41:22  03:56:23       0
5   18:58:26  19:16:49       0
6   20:12:37  20:52:49       0
7   20:55:16  22:02:50       0
8   22:21:24  22:48:50       0
9   23:11:30  00:00:00       0

這些重復記錄需要在isDup列更新為 1。


示例 2:

另一個數據示例如下。 在這里,雖然用戶仍然在13:36:1013:50:16之間登錄,但還有 3 個額外的會話需要標記。

  start_time  end_time
0   13:32:54  13:32:55
1   13:36:10  13:50:16
2   13:37:54  13:38:14
3   13:46:38  13:46:45
4   13:48:59  13:49:05
5   13:50:16  13:50:20
6   14:03:39  14:03:49
7   15:36:20  15:36:20
8   15:46:47  15:46:47

預期輸出:

  start_time    end_time    isDup
0   13:32:54    13:32:55    0
1   13:36:10    13:50:16    0
2   13:37:54    13:38:14    1
3   13:46:38    13:46:45    1
4   13:48:59    13:49:05    1
5   13:50:16    13:50:20    0
6   14:03:39    14:03:49    0
7   15:36:20    15:36:20    0
8   15:46:47    15:46:47    0

將當前記錄的開始時間與以前的記錄進行比較的有效方法是什么?

查詢duplicated()並將 astype 更改為int

df['isDup']=(df['Start time'].duplicated(False)|df['End time'].duplicated(False)).astype(int)

或者你需要

df['isDup']=(df['Start time'].between(df['Start time'].shift(),df['End time'].shift())).astype(int)

start_timeend_time列中的類似timeend_timeTimeDelta對象,並從end_time列中的00:00:00 timedelta 值中減去1 seconds

c = ['start_time', 'end_time']
s, e = df[c].astype(str).apply(pd.to_timedelta).to_numpy().T
e[e == pd.Timedelta(0)] += pd.Timedelta(days=1, seconds=-1)

然后對於數據幀df中的每一對start_timeend_time使用numpy broadcasting標記相應的重復間隔:

m = (s[:, None] >= s) & (e[:, None] <= e)
np.fill_diagonal(m, False)
df['isDupe'] = (m.any(1) & ~df[c].duplicated(keep=False)).view('i1')

# example 1
  start_time  end_time  isDupe
0   00:12:38  01:00:02       0
1   00:55:14  01:00:02       1
2   01:00:02  01:32:40       0
3   01:00:02  01:08:40       1
4   01:41:22  03:56:23       0
5   18:58:26  19:16:49       0
6   20:12:37  20:52:49       0
7   20:55:16  22:02:50       0
8   22:21:24  22:48:50       0
9   23:11:30  00:00:00       0

# example 2
  start_time  end_time  isDupe
0   13:32:54  13:32:55       0
1   13:36:10  13:50:16       0
2   13:37:54  13:38:14       1
3   13:46:38  13:46:45       1
4   13:48:59  13:49:05       1
5   13:50:16  13:50:20       0
6   14:03:39  14:03:49       0
7   15:36:20  15:36:20       0
8   15:46:47  15:46:47       0

這是我對上述問題的解決方案。 但是,如果有任何有效的方法,我會很樂意接受。 謝謝!

def getDuplicate(data):
    data['check_time'] = data.iloc[-1]['start_time']
    data['isDup'] = data.apply(lambda x: 1 
                               if (x['start_time'] <= x['check_time']) & (x['check_time'] < x['end_time']) 
                               else 0 
                               , axis = 1)

    return data['isDup'].sum()

limit = 1
df_copy = df.copy()
df['isDup'] = 0

for i, row in df.iterrows():
    data = df_copy.iloc[:limit]
    isDup = getDuplicate(data)
    limit = limit + 1

    if isDup > 1:
        df.at[i, 'isDup'] = 1
    else:
        df.at[i, 'isDup'] = 0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM