Python 工程进度表中的异常值

Python 工程进度表中的异常值,python,statistics,time-series,data-science,outliers,Python,Statistics,Time Series,Data Science,Outliers,我试图为个人的工作计划寻找异常值(主要是高变化)。如果有人在个人(上午8:30到下午5点)或团体正常(上午7点到下午6点)以外的地方来或离开,尝试寻找。我试着用标准差,但问题是 它给出了平均值两边的异常值。也就是说,如果一些人在工作时间迟到(比如上午10点)或早退(比如下午4点) 另一个问题是平均数本身。如果在数据集的开头有几个极端,则需要大量观察才能将平均值降到最频繁的时间。例如,一组在下午3点、上午11点、上午10点、上午9点左右的时间很少,但大多数时间在上午6点左右,但平均值需要大量观察才

我试图为个人的工作计划寻找异常值(主要是高变化)。如果有人在个人(上午8:30到下午5点)或团体正常(上午7点到下午6点)以外的地方来或离开,尝试寻找。我试着用标准差,但问题是

  • 它给出了平均值两边的异常值。也就是说,如果一些人在工作时间迟到(比如上午10点)或早退(比如下午4点)
  • 另一个问题是平均数本身。如果在数据集的开头有几个极端,则需要大量观察才能将平均值降到最频繁的时间。例如,一组在下午3点、上午11点、上午10点、上午9点左右的时间很少,但大多数时间在上午6点左右,但平均值需要大量观察才能得到上午6点的平均值。我想到了加权平均数,但这意味着我必须将时间四舍五入到最接近的30分钟左右。但希望避免更改数据点
  • 是否有任何已知的方法可以在工作计划中找到异常值?我试图搜索,但我得到的只是时间序列中的异常值。但我在寻找时间本身的异常值。有什么建议吗


    注意:我的数据集有PersonID和多次(刷卡)次数/天/PersonID。我使用的是Python2.7。

    如果我理解正确的话,您希望识别出与自身和整体标准相比,非常早出发或非常晚到达的人

  • 您遇到的第一个问题似乎与标记晚或早偏离(nx标准偏差)的异常值有关。您应该能够控制是在一侧还是两侧标记异常值
  • 第二个问题与小样本的平均值有偏差或不稳定有关。 除非您提前知道异常值阈值,否则在任何情况下都需要一个健康的样本来识别异常值。如果平均值没有足够快地归零到公共值,以及 你寻找共同的价值,使用模式而不是平均值
  • 此外,我建议将每天到达和离开的时间差作为一个单独的指标

    下面我有一个方向性的方法/建议来解决您的问题,python3(对不起)。
    它应该解决你提到的问题,但不增加我认为你应该包括的每日工作时间

    这是您可以期望的输出:

    Outlier PersonIDs based on overall data
    array([ 1.,  4.,  7.,  8.])
    Outlier PersonIDs based on each user's data and overall deviation
    array([ 1.,  3.,  4.,  5.,  7.,  8.,  9.])
    
    这是每日到达和离开时间分布:

    代码如下:

    #! /usr/bin/python3
    
    import random
    import pandas as pd
    import numpy as np
    import scipy.stats
    import pprint
    pp = pprint.PrettyPrinter(indent=4)
    
    # Visualize:
    import matplotlib.pyplot as plt
    
    #### Create Sample Data START
    # Parameters:
    TimeInExpected=8.5 # 8:30am
    TimeOutExpected=17 # 5pm
    sig=1 # 1 hour variance
    Persons=11
    # Increasing the ratio between sample size and persons will make more people outliers.
    SampleSize=20
    Accuracy=1 # Each hour is segmented by hour tenth (6 minutes)
    
    # Generate sample
    SampleDF=pd.DataFrame([
        np.random.randint(1,Persons,size=(SampleSize)),
        np.around(np.random.normal(TimeInExpected, sig,size=(SampleSize)),Accuracy),
        np.around(np.random.normal(TimeOutExpected, sig,size=(SampleSize)),Accuracy)
        ]).T
    SampleDF.columns = ['PersonID', 'TimeIn','TimeOut']
    
    # Visualize
    plt.hist(SampleDF['TimeIn'],rwidth=0.5,range=(0,24))
    plt.hist(SampleDF['TimeOut'],rwidth=0.5,range=(0,24))
    plt.xticks(np.arange(0,24, 1.0))
    plt.xlabel('Hour of day')
    plt.ylabel('Arrival / Departure Time Frequency')
    plt.show()
    #### Create Sample Data END
    
    
    #### Analyze data 
    # Threshold distribution percentile
    OutlierSensitivity=0.05 # Will catch extreme events that happen 5% of the time. - one sided! i.e. only late arrivals and early departures.
    presetPercentile=scipy.stats.norm.ppf(1-OutlierSensitivity)
    
    # Distribution feature and threshold percentile
    argdictOverall={
        "ExpIn":SampleDF['TimeIn'].mode().mean().round(1)
        ,"ExpOut":SampleDF['TimeOut'].mode().mean().round(1)
        ,"sigIn":SampleDF['TimeIn'].var()
        ,"sigOut":SampleDF['TimeOut'].var()
        ,"percentile":presetPercentile
    }
    OutlierIn=argdictOverall['ExpIn']+argdictOverall['percentile']*argdictOverall['sigIn']
    OutlierOut=argdictOverall['ExpOut']-argdictOverall['percentile']*argdictOverall['sigOut']
    
    # Overall
    # See all users with outliers - overall
    Outliers=SampleDF["PersonID"].loc[(SampleDF['TimeIn']>OutlierIn) | (SampleDF['TimeOut']<OutlierOut)]
    
    # See all observations with outliers - Overall
    # pp.pprint(SampleDF.loc[(SampleDF['TimeIn']>OutlierIn) | (SampleDF['TimeOut']<OutlierOut)].sort_values(["PersonID"]))
    
    # Sort and remove NAs
    Outliers=np.sort(np.unique(Outliers))
    # Show users with overall outliers:
    print("Outlier PersonIDs based on overall data")
    pp.pprint(Outliers)
    
    # For each
    OutliersForEach=[]
    for Person in SampleDF['PersonID'].unique():
        # Person specific dataset
        SampleDFCurrent=SampleDF.loc[SampleDF['PersonID']==Person]
        # Distribution feature and threshold percentile
        argdictCurrent={
            "ExpIn":SampleDFCurrent['TimeIn'].mode().mean().round(1)
            ,"ExpOut":SampleDFCurrent['TimeOut'].mode().mean().round(1)
            ,"sigIn":SampleDFCurrent['TimeIn'].var()
            ,"sigOut":SampleDFCurrent['TimeOut'].var()
            ,"percentile":presetPercentile
        }
        OutlierIn=argdictCurrent['ExpIn']+argdictCurrent['percentile']*argdictCurrent['sigIn']
        OutlierOut=argdictCurrent['ExpOut']-argdictCurrent['percentile']*argdictCurrent['sigOut']
        if SampleDFCurrent['TimeIn'].max()>OutlierIn or SampleDFCurrent['TimeOut'].min()<OutlierOut:
            Outliers=np.append(Outliers,Person)
    
    # Sort and get unique values
    Outliers=np.sort(np.unique(Outliers))
    # Show users with overall outliers:
    print("Outlier PersonIDs based on each user's data and overall deviation")
    pp.pprint(Outliers)
    
    #/usr/bin/python3
    随机输入
    作为pd进口熊猫
    将numpy作为np导入
    导入scipy.stats
    导入pprint
    pp=pprint.预印机(缩进=4)
    #想象:
    将matplotlib.pyplot作为plt导入
    ####创建示例数据开始
    #参数:
    预计时间=上午8.5#8:30
    预计时间=17#下午5点
    sig=1#1小时差异
    人数=11人
    #增加样本量和人数之间的比率将使更多的人成为异常值。
    样本大小=20
    精度=1#每小时按10小时(6分钟)分段
    #生成样本
    SampleDF=pd.DataFrame([
    np.random.randint(1,Persons,size=(SampleSize)),
    np.around(np.random.normal(未预测时间,信号,大小=(样本大小)),准确度),
    np.around(np.random.normal(TimeOutExpected,sig,size=(SampleSize)),精度)
    ])T
    SampleDF.columns=['PersonID','TimeIn','TimeOut']
    #想象
    plt.hist(SampleDF['TimeIn'],rwidth=0.5,范围=(0,24))
    plt.hist(SampleDF['TimeOut'],rwidth=0.5,范围=(0,24))
    plt.xticks(np.arange(0,24,1.0))
    plt.xlabel(“一天中的小时”)
    plt.ylabel(“到达/离开时间频率”)
    plt.show()
    ####创建示例数据结束
    ####分析数据
    #阈值分布百分位数
    异常敏感度=0.05#将捕获5%时间内发生的极端事件。-片面的!i、 e.只有迟到和早退。
    预设百分位=scipy.stats.norm.ppf(1-异常敏感度)
    #分布特征与阈值百分位数
    总体而言={
    “ExpIn”:SampleDF['TimeIn'].mode().mean().round(1)
    ,“ExpOut”:SampleDF['TimeOut'].mode().mean().round(1)
    ,“sigIn”:SampleDF['TimeIn'].var()
    ,“sigOut”:SampleDF['TimeOut'].var()
    ,“百分位数”:预设的百分位数
    }
    OutlierIn=argdictOverall['ExpIn']+argdictOverall['percentile']*argdictOverall['sigIn']
    OutlierOut=argdictOverall['ExpOut']-argdictOverall['percentile']*argdictOverall['sigOut']
    #总体上
    #查看所有具有异常值的用户-总体
    
    离群值=SampleDF[“PersonID”].loc[(SampleDF['TimeIn']>OutlierIn)|(SampleDF['TimeOut']OutlierIn)|(SampleDF['TimeOut']OutlierIn或SampleDFCurrent['TimeOut'].min()这是一种分析方法的建议(离群值检测)还有不完美的,生产级的,代码。我知道有些重复可能会被包装在函数和其他优化中。谢谢@AChervony,我并不期待有代码,但谢谢你这么做,这让它更容易理解。这接近我要找的。我更希望有人能表现得太过耳或者很晚才离开。目的不是跟踪时间,而是发现人们在无人在场的情况下呆在家里的风险。啊,明白了。我很高兴这有帮助。我还建议你添加其他指标。比如一周中的哪一天,是否是假期前一天,等等。你可以进行聚类或回归,以确定其他指标是否需要更改o与“风险”相关的事件。祝你好运!