如何自动识别DataFrame中各DateTime列的日期时间序列频率
实现方案
核心思路
- 优先使用pandas内置的
pd.infer_freq()做基础识别,适配绝大多数标准频率场景 - 新增相邻日期差值统计逻辑作为兜底,解决缺失值、非标准频率场景下识别失效的问题
- 增加月、年的首尾日期校验,精准区分自然月/年、固定间隔N天的场景
完整可运行代码
import pandas as pd # 构造示例DataFrame,你可以替换成自己的实际数据 data = [ ["1/26/2020", "2021-6-9", "2019/2/28"], ["2/2/2020", "2021-6-8", "2019/3/31"], ["2/9/2020", "2021-6-7", "2019/4/30"], ["2/16/2020", "2021-6-6", "2019/5/31"] ] df = pd.DataFrame(data, columns=['col1', 'col2', 'col3']) # 批量转为datetime类型,如果你已经是datetime类型可跳过这一步 df = df.apply(pd.to_datetime) def get_date_freq(series: pd.Series) -> str: # 预处理:去空、去重、排序 s = series.dropna().sort_values().drop_duplicates() if len(s) < 2: return "数据量不足无法识别" # 优先用pandas内置方法识别标准频率 inferred_freq = pd.infer_freq(s) if inferred_freq: return inferred_freq # 内置识别失效时,用间隔统计兜底 deltas = s.diff().dropna() most_common_delta = deltas.mode().iloc[0] days = most_common_delta.days if days == 1: return "D" elif days % 7 == 0: return f"{days//7}W" elif 28 <= days <= 31: # 校验是否为自然月 if s.dt.is_month_end.all(): return "M" elif s.dt.is_month_start.all(): return "MS" else: return f"{days}D" elif 365 <= days <= 366: # 校验是否为自然年 if s.dt.is_year_end.all(): return "A" elif s.dt.is_year_start.all(): return "AS" else: return f"{days}D" else: return f"{days}D" # 批量识别所有列的频率 freq_result = df.apply(get_date_freq) print(freq_result)
示例输出
针对你给出的示例数据,运行后输出结果如下:
col1 W-SUN col2 D col3 M dtype: object
和预期完全匹配:第一列为周频率、第二列为日频率、第三列为月末频率。
注意事项
- 可以根据业务需求修改函数内的频率映射规则,适配季度、小时级等特殊频率识别
- 如果列内存在异常日期,建议先做异常值过滤再识别,避免结果偏差
内容的提问来源于stack exchange,提问作者YazeedHasan
相关产品推荐
相关产品推荐

