代码之家  ›  专栏  ›  技术社区  ›  DanP

创建给定班次列表的时间表的摘要描述

  •  5
  • DanP  · 技术社区  · 14 年前

    通常 发生。

    我想我正在寻找某种统计方法来确定发生的日期和时间,并根据列表中发现的最频繁的事件创建一个描述。对于这样的事情有什么通用的算法吗?有人创造过类似的东西吗?

    提前谢谢!

    4 回复  |  直到 12 年前
        1
  •  12
  •   Community rohancragg    4 年前

    你可以用 Cluster Analysis .

    聚类是一种将一组数据分离成相似组件(子集)的方法。“相似性”概念涉及点之间“距离”的一些定义。存在许多常用的距离公式,其中包括常用的欧几里德距离。

    实际案例

    在向您指出该行业的怪癖之前,让我们为您的问题展示一个实际案例,这样您就可以参与到算法和包中,或者预先丢弃它们。

    为了方便起见,我用Mathematica对这个问题进行了建模,因为软件中包含了聚类分析,而且设置起来非常简单。


    开始时间和结束时间加上一个随机变量(+半小时,零,-半小时},以显示算法处理“噪声”的能力。

    一共有三天,每天三班,还有一个额外的(最后一个)“异常”班,从早上7点开始,到早上9点结束(可怜的家伙!)。

    每个“正常”班次有150个事件,例外班次只有两个事件。

    我包括在Mathematica的代码,以防你有权访问该软件。我试图避免使用函数语法,使代码更易于“外国人”阅读。

    Rn[] := 0.5 * RandomInteger[{-1, 1}];
    
    monshft1 = Table[{ 1 , 10 + Rn[] , 15 + Rn[] }, {150}];  // 1
    monshft2 = Table[{ 1 , 12 + Rn[] , 17 + Rn[] }, {150}];  // 2
    wedshft1 = Table[{ 3 , 10 + Rn[] , 15 + Rn[] }, {150}];  // 3
    wedshft2 = Table[{ 3 , 14 + Rn[] , 17 + Rn[] }, {150}];  // 4
    frishft1 = Table[{ 5 , 10 + Rn[] , 15 + Rn[] }, {150}];  // 5
    frishft2 = Table[{ 5 , 11 + Rn[] , 15 + Rn[] }, {150}];  // 6
    monexcp  = Table[{ 1 , 7  + Rn[] , 9  + Rn[] }, {2}];    // 7
    

    现在我们加入数据,得到一个大数据集:

    data = Join[monshft1, monshft2, wedshft1, wedshft2, frishft1, frishft2, monexcp];
    

    让我们对数据进行聚类分析:

    clusters = FindClusters[data, 7, Method->{"Agglomerate","Linkage"->"Complete"}]
    

    “凝聚”与“联动”->Complete”是Mathematica中实现的聚类方法的两个微调选项。他们只是指出,我们正试图找到非常紧凑的集群。

    我们可以得到一个带有结果的图表,每个聚类都有不同的颜色(不介意代码)

    ListPointPlot3D[ clusters, 
               PlotStyle->{{PointSize[Large], Pink},    {PointSize[Large], Green},   
                           {PointSize[Large], Yellow},  {PointSize[Large], Red},  
                           {PointSize[Large], Black},   {PointSize[Large], Blue},   
                           {PointSize[Large], Purple},  {PointSize[Large], Brown}},  
                           AxesLabel -> {"DAY", "START TIME", "END TIME"}]  
    

    alt text

    因此,我们将得到每个簇并取平均值(四舍五入):

    Table[Round[Mean[clusters[[i]]]], {i, 7}]  
    

    Day   Start  End
    {"1", "10", "15"},
    {"1", "12", "17"},
    {"3", "10", "15"},
    {"3", "14", "17"},
    {"5", "10", "15"},
    {"5", "11", "15"},
    {"1",  "7",  "9"}
    

    现在,也许你想把班次分类,不管是哪一天。如果同样的人每天在同一时间做同样的工作,那么称之为“星期一从10点到15点”是没有用的,因为它也发生在星期三和星期五(如我们的例子)。

    让我们分析数据,忽略第一列:

    clusters=
     FindClusters[Take[data, All, -2],Method->{"Agglomerate","Linkage"->"Complete"}];
    

    在这种情况下,我们没有选择要检索的集群数量,而是将决策权留给包。

    image

    你可以看到已经确定了五个集群。

    让我们试着像以前一样给他们贴上“标签”:

    Grid[Table[Round[Mean[clusters[[i]]]], {i, 5}]]
    

     START  END
    {"10", "15"},
    {"12", "17"},
    {"14", "17"},
    {"11", "15"},
    { "7",  "9"}
    

    这正是我们“怀疑”的:每天在同一时间都有重复的事件可以组合在一起。

    如果你有(或计划有)一天开始,一天结束的班次,最好的模式

    {Start-Day Start-Hour Length}  // Correct!
    

    {Start-Day Start-Hour End-Day End-Hour}  // Incorrect!  
    

    这是因为与任何统计方法一样,变量之间的相关性必须明确,否则该方法将惨败。这个原则可以运行类似于“保持候选人数据的标准化”。两个概念几乎相同(属性应该是独立的)。

    ---编辑结束---

    到现在为止,我想你已经很清楚这种分析能做什么了。

    一些参考文献

    1. 当然, Wikipedia 其“参考文献”和“进一步阅读”是很好的指南。
    2. here 展示了Statsoft的功能,但是你可以得到很多 关于你可以用这个算法做的其他事情的想法。
    3. Here 是对所涉及算法的基本解释
    4. Here R R 是一个很好的选择)
    5. 最后, here 你可以找到一长串的免费的和商业的统计软件,包括集群。

    嗯!

        2
  •  1
  •   Grzenio    14 年前

    我会从将你的班次划分为工作日开始(因为如果我理解正确的话,你是在每周查看之后),所以每个工作日我们都有恰好在那一天的班次。然后,每天我都会对同时发生的班次进行分组(或“大致”在同一时间——这里你需要提出一些启发,即开始和结束时间与组中平均值的偏差不会超过15分钟或30分钟)。现在我们需要另一个启发来决定这个群体是否相关,也就是说,如果周一下午1点到3点的班次只发生过一次,那么这个班次可能不相关,但是如果它发生在数据覆盖的至少70%的周一,那么这个班次是相关的。现在,一周中每一天的相关小组都将形成你所追求的时间表。

        3
  •  0
  •   Peter Hanneman    14 年前

    我们能看一个示例数据集吗?如果它真的是“干净”的数据,那么您可以简单地找到开始和结束时间的模式。

        4
  •  0
  •   Grembo    14 年前

    一个选项是将所有开始时间标记为+1,结束时间标记为-1,然后创建一个三列的时间表(包括开始时间和结束时间)、标签(+1或-1)和当时的员工人数(从零开始,使用标签添加或减去员工),并按时间顺序对整个事情进行排序。

    这个时间序列现在是员工级别的摘要描述符,标签也是一个序列。现在,您可以将时间序列统计信息应用于这两者,以查找每日、每周或每月的模式。