在给定班次列表的情况下创建计划的摘要描述

时间:2010-07-02 13:03:49

标签: c# vb.net statistics cluster-analysis

假设我有一个事件的班次列表(格式为开始日期/时间,结束日期/时间) - 是否有某种算法可用于创建日程安排的概括?大多数轮班经常会出现某种常见的复发模式(即周一从上午9:00到下午1:00,周二从上午10:00到下午3:00等)。但是,这条规则可以(并且将会是)例外(例如,其中一个班次在假期降低,并在第二天重新安排)。从我的“摘要”中排除这些内容会很好,因为我希望提供一个更通用的答案,说明此事件通常何时发生。

我想我正在寻找某种统计方法来确定出现的日期和时间,并根据列表中最常见的出现次数创建描述。对于像这样的东西,有某种通用算法吗?有没有人创造过类似的东西?

理想情况下,我在寻找C#或VB.NET的解决方案,但不介意从任何其他语言移植。

提前致谢!

4 个答案:

答案 0 :(得分:11)

您可以使用Cluster Analysis

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

实际案例

在向您指出交易的怪癖之前,让我们为您的问题展示一个实际案例,这样您就可以参与算法和软件包,或者提前将它们丢弃。

为了方便起见,我在Mathematica中对问题进行了建模,因为Cluster Analysis包含在软件中并且非常简单易于设置。

首先,生成数据。格式为{DAY,START TIME,END TIME} 开始和结束时间添加了一个随机变量(+半小时,零,半小时),以显示算法处理“噪音”的能力。

有三天,每天三班,一个额外(最后一个)“异常”班次,从上午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"}]

“聚集”和“联系” - > “完成”是Mathematica中实现的聚类方法的两个微调选项。他们只是指出我们正在努力寻找非常紧凑的集群。

我指定尝试检测7个群集。如果正确的移位数未知,您可以尝试几个合理的值并查看结果,或让算法选择更合适的值。

我们可以得到一个包含结果的图表,每个群集都有不同的颜色(不介意代码)

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 http://i28.tinypic.com/2hmdlab.png

你可以清楚地看到我们的七个星团分开。

这解决了部分问题:识别数据。现在你也希望能够标记它。

因此,我们将获得每个集群并采取方法(四舍五入):

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”是没有用的,因为它也发生在Weds和Fridays(如我们的例子中)。

让我们分析一下无视第一栏的数据:

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

在这种情况下,我们不会选择要检索的群集数量,而是将决定留给包裹。

结果是

image http://i27.tinypic.com/mise9.png

您可以看到已识别出五个群集。

让我们像以前一样“标记”它们:

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您可以找到一长串免费和商业软件的统计数据,包括群集。
  6. HTH!

答案 1 :(得分:1)

我不认为任何现成的算法存在,所以不幸的是你需要自己想出一些东西。因为这个问题没有得到很好的定义(从数学的角度来看),所以需要测试一些具有合理代表性的“真实”数据,并进行相当多的调整。

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

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