作者:小小明,Pandas資料處理專家,致力于幫助無數資料從業者解決資料處理難題,
需求說明
有一份下面格式用戶游覽日志的資料(復制下面顯示的表格后,運行下面的代碼才會出現相同的結果):
import pandas as pd
df = pd.read_clipboard()
df
結果:
| uid | start | end | |
|---|---|---|---|
| 0 | A | 1 | 2 |
| 1 | A | 4 | 7 |
| 2 | A | 3 | 6 |
| 3 | A | 8 | 9 |
| 4 | B | 2 | 3 |
| 5 | B | 4 | 7 |
| 6 | B | 10 | 11 |
| 7 | B | 6 | 8 |
| 8 | B | 12 | 15 |
| 9 | C | 14 | 15 |
其中uid表示每個用戶,start表示起始游覽時間,end表示結束游覽的時間,從上表可以看到,存在游覽時間重疊的情況,例如用戶A的游覽時間3-6和4-7重疊,可以認為游覽時間是3-7,
我們現在要做的事就是把每個用戶的存在重疊的游覽時間合并到一起,最終并按照時間順序排序顯示,
注意:3-4和4-6也屬于重疊的時間,可以合并為3-6,
先對一個用戶進行時間合并并排序
取出一個用戶的資料,用于測驗操作:
tmp = df.groupby("uid").get_group('B')
tmp
結果:
| uid | start | end | |
|---|---|---|---|
| 4 | B | 2 | 3 |
| 5 | B | 4 | 7 |
| 6 | B | 10 | 11 |
| 7 | B | 6 | 8 |
| 8 | B | 12 | 15 |
觀察發現,要解決這個問題,我們首先需要對資料按照開始時間排序,

排序后:
tmp = tmp.sort_values('start')
tmp
結果:
| uid | start | end | |
|---|---|---|---|
| 4 | B | 2 | 3 |
| 5 | B | 4 | 7 |
| 7 | B | 6 | 8 |
| 6 | B | 10 | 11 |
| 8 | B | 12 | 15 |
觀察排序后的資料,我們就能很快的觀察出合并的規則:
當前游覽記錄的的起始時間小于等于上一條記錄的結束時間時就進行合并,非常簡單:
result = []
for uid, start, end in tmp.values:
# 如果結果集中還沒有資料或者當前記錄的起始時間大于上一條記錄的結束時間
# 就可以直接將當前記錄加入到結果集
if not result or start > result[-1][2]:
result.append([uid, start, end])
else:
# 否則,說明可以將當前記錄與上一條記錄合并
# 合并方法是如果當前記錄的結束時間大于上一條記錄的結束時間,
# 則上一條記錄的結束時間修改為當前記錄的結束時間
result[-1][2] = max(result[-1][2], end)
tmp = pd.DataFrame(result, columns=["uid", "start", "end"])
tmp
結果:
| uid | start | end | |
|---|---|---|---|
| 0 | B | 2 | 3 |
| 1 | B | 4 | 8 |
| 2 | B | 10 | 11 |
| 3 | B | 12 | 15 |
完整代碼
然后我們整理一下完整的處理代碼:
result = []
for uid, tmp in df.groupby("uid"):
tmp = tmp[["start", "end"]].sort_values('start')
rows = []
for start, end in tmp.values:
if not rows or start > rows[-1][2]:
rows.append([uid, start, end])
else:
rows[-1][2] = max(rows[-1][2], end)
tmp = pd.DataFrame(rows, columns=["uid", "start", "end"])
result.append(tmp)
result = pd.concat(result)
result
結果:
| uid | start | end | |
|---|---|---|---|
| 0 | A | 1 | 2 |
| 1 | A | 3 | 7 |
| 2 | A | 8 | 9 |
| 0 | B | 2 | 3 |
| 1 | B | 4 | 8 |
| 2 | B | 10 | 11 |
| 3 | B | 12 | 15 |
| 0 | C | 14 | 15 |
好了,完結,撒花!
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/247205.html
標籤:其他
