DataFrame多日期列冲突处理:基于多数一致规则的简洁实现问询
嘿,这个需求我之前也碰到过,用一堆嵌套ifelse确实太啰嗦了,给你几个简洁又高效的实现方式,不管是小数据集还是大数据量都能搞定~
方法1:利用众数(
mode())快速匹配规则 Pandas里的mode()方法天生适合这种「找出现次数最多的值」的场景,完美匹配你的需求:
- 至少两个日期一致时,众数就是这个重复的日期,直接取即可
- 三个日期都不同时,
mode()会返回所有值,我们判断后返回NA - 两个NA+一个有效日期时,唯一的非空值就是众数,自动保留
import pandas as pd import numpy as np # 构造测试数据 df = pd.DataFrame({ 'id': [1,2,3,4,5], 'date1': ['2023-01-01', '2023-02-02', '2023-03-03', '2023-04-04', np.nan], 'date2': ['2023-01-01', '2023-02-02', '2023-03-04', np.nan, np.nan], 'date3': ['2023-01-01', '2023-02-03', '2023-03-05', np.nan, '2023-05-05'] }) def resolve_dates(row): # 过滤当前行的空值 non_null_dates = row.dropna() if len(non_null_dates) == 0: return np.nan # 计算众数 mode_results = non_null_dates.mode() # 规则判断:众数唯一(出现>=2次)或只有一个非空值时返回,否则返回NA if len(mode_results) == 1 or len(non_null_dates) == 1: return mode_results.iloc[0] else: return np.nan # 应用到每行生成结果列 df['resolved_date'] = df[['date1', 'date2', 'date3']].apply(resolve_dates, axis=1)
方法2:用
value_counts()统计出现次数(更直观) 这个思路更直白:对每行的非空日期统计出现次数,按次数直接判断规则:
def resolve_dates_v2(row): non_null_dates = row.dropna() if len(non_null_dates) == 0: return np.nan # 统计每个日期的出现次数 date_counts = non_null_dates.value_counts() # 最多出现次数>=2则返回该日期;只有一个非空值也返回;否则(三个都不同)返回NA if date_counts.iloc[0] >= 2 or len(non_null_dates) == 1: return date_counts.index[0] else: return np.nan df['resolved_date_v2'] = df[['date1', 'date2', 'date3']].apply(resolve_dates_v2, axis=1)
方法3:矢量化处理(适合大数据集)
如果你的数据集行数很多,apply的效率可能不够,试试矢量化的方式,全程用Pandas的分组、聚合操作实现:
# 把宽表转成窄表,方便分组统计 melted_df = df.melt( id_vars='id', value_vars=['date1', 'date2', 'date3'], value_name='date' ).dropna(subset=['date']) # 统计每个id下各日期的出现次数 date_counts = melted_df.groupby(['id', 'date']).size().reset_index(name='count') # 找出每个id的最大出现次数 max_counts = date_counts.groupby('id')['count'].max().reset_index(name='max_count') # 合并数据并按规则生成结果 final_results = date_counts.merge(max_counts, on='id').groupby('id').apply( lambda x: x['date'].iloc[0] if (x['max_count'].iloc[0] >=2 or len(x)==1) else np.nan ).reset_index(name='resolved_date') # 合并回原DataFrame df = df.merge(final_results, on='id')
这些方法都比嵌套ifelse简洁太多,逻辑也更清晰,你可以根据自己的数据集大小选择合适的方式~
内容的提问来源于stack exchange,提问作者user1165199
相关产品推荐
相关产品推荐

