You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自动识别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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 23:45:02