如何去除DataFrame同一时间戳重复行并保留Online状态数据?
解决DataFrame按时间戳去重并优先保留Online状态行的问题
需求说明
- 去除DataFrame中同一时间戳下的完全重复行
- 同一时间戳下同时存在
Offline和Online状态时,保留Online状态的行
数据准备
创建目标DataFrame的代码
hf = sf0.loc[(sf0['provider_id'] == '0037dfffff8b03bbdf366a263735e84b') & (sf0['Date'] == '2017-09-04')].sort_values('Time')
示例数据
provider_id dt Status Date Time 372 0037dfffff8b03bbdf366a263735e84b 2017-09-04 08:00:19 Online 2017-09-04 08:00:19 426 0037dfffff8b03bbdf366a263735e84b 2017-09-04 08:29:39 Offline 2017-09-04 08:29:39 443 0037dfffff8b03bbdf366a263735e84b 2017-09-04 08:44:36 Offline 2017-09-04 08:44:36 450 0037dfffff8b03bbdf366a263735e84b 2017-09-04 09:06:12 Online 2017-09-04 09:06:12 404 0037dfffff8b03bbdf366a263735e84b 2017-09-04 12:23:24 Offline 2017-09-04 12:23:24 402 0037dfffff8b03bbdf366a263735e84b 2017-09-04 12:23:47 Offline 2017-09-04 12:23:47 354 0037dfffff8b03bbdf366a263735e84b 2017-09-04 12:45:46 Offline 2017-09-04 12:45:46 538 0037dfffff8b03bbdf366a263735e84b 2017-09-04 12:45:46 Online 2017-09-04 12:45:46 387 0037dfffff8b03bbdf366a263735e84b 2017-09-04 12:45:56 Offline 2017-09-04 12:45:56 419 0037dfffff8b03bbdf366a263735e84b 2017-09-04 17:38:31 Offline 2017-09-04 17:38:31 493 0037dfffff8b03bbdf366a263735e84b 2017-09-04 17:38:31 Online 2017-09-04 17:38:31 494 0037dfffff8b03bbdf366a263735e84b 2017-09-04 17:40:51 Online 2017-09-04 17:40:51
问题分析
原代码hf.groupby('Time').first().drop_duplicates()存在两个核心问题:
- 未先处理完全重复行,可能导致无效数据残留
groupby('Time').first()会按原DataFrame的行顺序取第一个值,若Offline行排在Online行前面,就会误删Online状态数据
解决方案
步骤1:先去除完全重复行
先删除所有列值完全相同的重复行:
# 去除完全重复行 hf_clean = hf.drop_duplicates()
步骤2:按时间戳分组,优先保留Online状态行
提供两种简洁的实现方式:
方式一:通过优先级排序实现
给Status设置优先级(Online优先级高于Offline),排序后按时间戳分组取第一行:
# 新增临时优先级列,Online标记为0,Offline标记为1(数值越小优先级越高) hf_clean['status_priority'] = hf_clean['Status'].map({'Online': 0, 'Offline': 1}) # 按Time分组,每组内按优先级升序排序,取第一行后删除临时优先级列 result = hf_clean.sort_values(['Time', 'status_priority']).groupby('Time').first().drop(columns='status_priority')
方式二:通过自定义分组函数实现
直接在分组时判断是否存在Online状态,存在则保留该行,否则保留任意一行:
result = hf_clean.groupby('Time').apply( lambda group: group[group['Status'] == 'Online'].iloc[0] if 'Online' in group['Status'].values else group.iloc[0] ).reset_index(drop=True)
验证结果
处理后的结果会保留每个时间戳的唯一行,且同一时间戳下同时存在两种状态时,仅保留Online行:
- 时间戳
2017-09-04 12:45:46保留Online行 - 时间戳
2017-09-04 17:38:31保留Online行 - 其余时间戳保留唯一状态行
内容的提问来源于stack exchange,提问作者Satyam Anand
相关产品推荐
相关产品推荐

