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

Python DataFrame中二进制月度数据的异常检测与值预测方法问询

二进制月度实体数据的简易异常检测方案

需求概述

需要为月度更新的二进制Exclusion字段(1=排除,0=纳入)构建异常检测机制,适配3000+实体的场景,核心诉求是基于历史数据(可限定最近N个月)预测下月最可能取值,标记不符合预期的变动,无需复杂机器学习模型。

预期检测规则参考:

  • 接受与历史完全一致的取值(如实体A持续为1)
  • 接受历史有变化但近期无波动的取值(如实体B后期稳定为1)
  • 接受切换为历史占比更高的取值(如实体C从1切回0,0为历史主流值)
  • 接受规律切换的取值(如实体D交替0/1)
  • 标记首次出现的新值(如实体E首次出现0)
  • 标记打破近期趋势的取值(如实体F打破连续3个月的1趋势切为0)

示例数据

import pandas as pd
d = {'Date': [20210101, 20210201,20210301,20210401,20210501,
              20210101, 20210201,20210301,20210401,20210501,
              20210101,20210201,20210301,20210401,20210501,
              20210101,20210201,20210301,20210401,20210501,
              20210101,20210201,20210301,20210401,20210501,
              20210101,20210201,20210301,20210401,20210501,], 
              
     'Entity': ['A','A','A','A','A',
                'B','B','B','B','B',
                'C','C','C','C','C',
                'D','D','D','D','D',
                'E','E','E','E','E',
                'F','F','F','F','F'],
    'Exclusion': [1,1,1,1,1,
                  0,0,0,1,1,
                  0,0,0,1,0,
                  1,0,1,0,1,
                  1,1,1,1,0,
                  0,1,1,1,0]}
df = pd.DataFrame(data=d)
# 转换日期格式并排序,确保时间顺序正确
df['Date'] = pd.to_datetime(df['Date'], format='%Y%m%d')
df = df.sort_values(['Entity', 'Date']).reset_index(drop=True)

简易解决方案

以下方案均基于Pandas分组操作,批量处理所有实体,代码易读易调整,适合新手。

方法1:近期频率多数投票(基础版)

核心逻辑:取每个实体最近N个月的历史值,预测出现次数最多的取值;若最新值与预测值不符,标记为可疑。

def predict_most_frequent(group, window=6):
    # 获取最近window条历史数据
    recent_vals = group['Exclusion'].tail(window)
    # 取出现次数最多的值(平局时默认取1,可按需修改)
    pred_val = recent_vals.mode().iloc[0] if not recent_vals.mode().empty else 1
    latest_val = group['Exclusion'].iloc[-1]
    # 标记可疑:至少有2条历史数据,且最新值≠预测值
    group['Suspicious'] = 0
    if len(recent_vals) >= 2 and latest_val != pred_val:
        group['Suspicious'].iloc[-1] = 1
    return group

# 按实体分组处理
result_df = df.groupby('Entity').apply(predict_most_frequent, window=6).reset_index(drop=True)

# 查看可疑记录
print(result_df[result_df['Suspicious'] == 1])

方法2:趋势+频率结合(进阶版)

针对打破近期连续趋势的情况(如实体F),优先判断近期连续取值,再结合多数投票:

def predict_trend_plus_freq(group, window=6, trend_window=3):
    recent_vals = group['Exclusion'].tail(window)
    latest_val = group['Exclusion'].iloc[-1]
    group['Suspicious'] = 0

    # 先检查近期连续趋势
    if len(recent_vals) >= trend_window:
        trend_vals = recent_vals.tail(trend_window)
        # 若最近trend_window个月取值完全一致
        if len(trend_vals.unique()) == 1:
            trend_pred = trend_vals.iloc[0]
            if latest_val != trend_pred:
                group['Suspicious'].iloc[-1] = 1
                return group
    
    # 无连续趋势时用多数投票判断
    pred_val = recent_vals.mode().iloc[0] if not recent_vals.mode().empty else 1
    if len(recent_vals) >= 2 and latest_val != pred_val:
        group['Suspicious'].iloc[-1] = 1
    return group

result_df = df.groupby('Entity').apply(predict_trend_plus_freq).reset_index(drop=True)

方法3:首次出现值检测(针对性版)

针对首次出现新值的情况(如实体E),单独判断历史是否出现过该值,再结合频率:

def predict_with_first_occurrence(group, window=6):
    latest_val = group['Exclusion'].iloc[-1]
    group['Suspicious'] = 0

    # 检查历史中是否出现过最新值
    has_historical = (group['Exclusion'].iloc[:-1] == latest_val).any()
    if not has_historical:
        group['Suspicious'].iloc[-1] = 1
        return group
    
    # 结合近期多数投票判断
    recent_vals = group['Exclusion'].tail(window)
    pred_val = recent_vals.mode().iloc[0] if not recent_vals.mode().empty else 1
    if len(recent_vals) >= 2 and latest_val != pred_val:
        group['Suspicious'].iloc[-1] = 1
    return group

result_df = df.groupby('Entity').apply(predict_with_first_occurrence).reset_index(drop=True)

方案优势

  • 批量处理:基于Pandas分组操作,轻松适配3000+实体的场景,运行效率高
  • 易维护:代码逻辑清晰,可根据实际需求调整窗口大小、平局规则等
  • 无依赖:无需额外机器学习库,仅用基础Pandas功能即可实现

内容的提问来源于stack exchange,提问作者gmerke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 18:50:24