如何在地震检测数据合并中去重,保留同时间事件单行
解决地震检测记录与P/S波数据合并时的重复行问题
核心问题分析
你遇到的重复行问题,本质是单个数据源内同一时间点存在多条记录,直接合并时触发笛卡尔积,同时未正确保留无对应数据的行。要实现同一时间(日期+小时)的检测、P波、S波记录合并为一行,缺省数据填充NaN,需要分两步处理:先统一时间键并聚合单数据源内的重复时间记录,再用全外连接合并三个数据集。
可复现方案与代码示例
1. 构造模拟数据(匹配业务场景)
import pandas as pd import numpy as np # A: 检测记录(含同一时间多条检测) A = pd.DataFrame({ 'date': ['2024-01-01', '2024-01-01', '2024-01-02'], 'hour': [10, 10, 14], 'detect_id': ['D001', 'D002', 'D003'], 'detect_result': ['positive', 'positive', 'negative'] }) # B: P波记录(含同一时间多条P波数据) B = pd.DataFrame({ 'date': ['2024-01-01', '2024-01-02', '2024-01-02'], 'hour': [10, 14, 14], 'p_wave_id': ['P001', 'P002', 'P003'], 'p_wave_amplitude': [0.8, 1.2, 0.9] }) # C: S波记录(含无对应检测/P波的时间点) C = pd.DataFrame({ 'date': ['2024-01-01', '2024-01-03'], 'hour': [10, 9], 's_wave_id': ['S001', 'S002'], 's_wave_duration': [12.5, 8.3] })
2. 统一时间键并聚合单数据源内的重复记录
先为每个数据集生成date_hour作为统一合并键,再对同一时间点的多条记录进行聚合(这里用列表存储同时间的多条记录,你也可以根据业务需求改为取第一条/最后一条、求均值等):
# 生成统一时间键(格式:YYYY-MM-DD HH) for df in [A, B, C]: df['date_hour'] = pd.to_datetime(df['date'] + ' ' + df['hour'].astype(str)).dt.strftime('%Y-%m-%d %H') # 聚合每个数据集内同一时间的多条记录 A_agg = A.groupby('date_hour').agg({ 'date': 'first', 'hour': 'first', 'detect_id': lambda x: list(x), 'detect_result': lambda x: list(x) }).reset_index() B_agg = B.groupby('date_hour').agg({ 'date': 'first', 'hour': 'first', 'p_wave_id': lambda x: list(x), 'p_wave_amplitude': lambda x: list(x) }).reset_index() C_agg = C.groupby('date_hour').agg({ 'date': 'first', 'hour': 'first', 's_wave_id': lambda x: list(x), 's_wave_duration': lambda x: list(x) }).reset_index()
3. 全外连接合并三个数据集
用how='outer'确保保留所有时间点,无对应数据自动填充NaN:
# 逐步合并:先合并检测记录与P波数据 merged = pd.merge(A_agg, B_agg, on='date_hour', how='outer', suffixes=('_detect', '_pwave')) # 再合并S波数据 merged = pd.merge(merged, C_agg, on='date_hour', how='outer', suffixes=('', '_swave')) # 合并重复的date/hour字段,保留有效数据 merged['date'] = merged['date_detect'].combine_first(merged['date_pwave']).combine_first(merged['date']) merged['hour'] = merged['hour_detect'].combine_first(merged['hour_pwave']).combine_first(merged['hour']) # 删除冗余字段并调整列顺序 merged.drop(['date_detect', 'date_pwave', 'hour_detect', 'hour_pwave'], axis=1, inplace=True) merged = merged[['date_hour', 'date', 'hour', 'detect_id', 'detect_result', 'p_wave_id', 'p_wave_amplitude', 's_wave_id', 's_wave_duration']] # 查看最终结果 print(merged)
最终输出示例
date_hour date hour detect_id detect_result p_wave_id p_wave_amplitude s_wave_id s_wave_duration 0 2024-01-01 10 2024-01-01 10 [D001, D002] [positive, positive] [P001] [0.8] [S001] [12.5] 1 2024-01-02 14 2024-01-02 14 [D003] [negative] [P002, P003] [1.2, 0.9] NaN NaN 2 2024-01-03 09 2024-01-03 9 NaN NaN NaN NaN [S002] [8.3]
为什么之前的方法无效?
- 直接用
merge/join未处理单数据源内的重复时间记录,会触发笛卡尔积,导致同一时间点生成多条重复行; - 未使用
how='outer'会丢失无对应检测/P波/S波的时间点; concat仅按行/列拼接,无法按时间键匹配数据。
内容的提问来源于stack exchange,提问作者Arlene Morel
相关产品推荐
相关产品推荐

