如何在Pandas中为IP-域名时序数据生成切换前置标记列
Pandas实现IP下域名切换前最后一条记录标记需求
嘿,这个需求用Pandas其实很好实现,我来给你拆解具体步骤和代码:
步骤说明
核心思路是通过分组排序、移位获取下一条数据、条件判断这三个环节来完成标记:
- 先确保时间戳是
datetime类型,保证数据按时间顺序处理; - 按IP分组后,获取每条记录的下一条域名,判断是否即将切换;
- 标记每个IP+域名组内的最后一条记录;
- 结合两个条件,最终生成
switch列。
完整代码实现
1. 构造示例数据(如果你已经有现成DataFrame可以跳过这步)
import pandas as pd data = { 'domain': ['Google', 'Google', 'Google', 'Facebook', 'Facebook', 'Youtube', 'Youtube', 'Youtube', 'Google', 'Facebook', 'Youtube'], 'ip': [101, 101, 101, 101, 101, 103, 103, 103, 103, 103, 103], 'timestamp': ['2020-04-01 23:01:41', '2020-04-01 23:01:59', '2020-04-02 12:01:41', '2020-04-02 13:11:33', '2020-04-02 13:11:35', '2020-04-21 13:01:41', '2020-04-21 13:11:46', '2020-04-22 01:01:01', '2020-04-22 02:11:23', '2020-04-23 14:11:13', '2020-04-23 14:11:55'] } df = pd.DataFrame(data) # 转换时间戳为datetime类型,确保排序正确 df['timestamp'] = pd.to_datetime(df['timestamp'])
2. 核心处理逻辑
# 按IP和时间戳排序,保证每个IP下的数据是时间顺序 df = df.sort_values(['ip', 'timestamp']).reset_index(drop=True) # 1. 获取每个IP分组内下一条记录的域名 df['next_domain'] = df.groupby('ip')['domain'].shift(-1) # 2. 标记当前记录是否为同一IP+域名组的最后一条 df['is_last_in_domain'] = df.groupby(['ip', 'domain']).cumcount(ascending=False) == 0 # 3. 生成switch列:满足「是当前域名组最后一条」且「下一条域名不同」且「不是IP的最后一条记录」 df['switch'] = ((df['is_last_in_domain']) & (df['domain'] != df['next_domain']) & (~df['next_domain'].isna())).astype(int) # 可选:清理临时生成的辅助列 df = df.drop(['next_domain', 'is_last_in_domain'], axis=1)
运行结果
执行完代码后,你会得到符合预期的DataFrame:
| domain | ip | timestamp | switch | |
|---|---|---|---|---|
| 0 | 101 | 2020-04-01 23:01:41 | 0 | |
| 1 | 101 | 2020-04-01 23:01:59 | 0 | |
| 2 | 101 | 2020-04-02 12:01:41 | 1 | |
| 3 | 101 | 2020-04-02 13:11:33 | 0 | |
| 4 | 101 | 2020-04-02 13:11:35 | 0 | |
| 5 | Youtube | 103 | 2020-04-21 13:01:41 | 0 |
| 6 | Youtube | 103 | 2020-04-21 13:11:46 | 0 |
| 7 | Youtube | 103 | 2020-04-22 01:01:01 | 1 |
| 8 | 103 | 2020-04-22 02:11:23 | 1 | |
| 9 | 103 | 2020-04-23 14:11:13 | 1 | |
| 10 | Youtube | 103 | 2020-04-23 14:11:55 | 0 |
关键逻辑解释
groupby('ip')['domain'].shift(-1):在每个IP分组内,将下一行的域名移到当前行,用来判断是否即将发生域名切换;groupby(['ip', 'domain']).cumcount(ascending=False) == 0:按IP+域名分组后,从后往前计数,计数为0的就是该组的最后一条记录;- 最后的条件判断同时排除了IP的最后一条记录(因为它的
next_domain为NaN,不会满足条件,自动设为0)。
内容的提问来源于stack exchange,提问作者Eisen
相关产品推荐
相关产品推荐

