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

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

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

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

提前致谢!

您可以使用Cluster Analysis 。

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

实际案例

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

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

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

有三天,每天三class,一个额外(最后一个)“exception”class次,从上午7点开始,到上午9点结束(可怜的家伙!)。

每个“正常”class次有150个事件,而在特殊class次中只有两个。

正如您所看到的,一些变化并不是很远。

我将代码包含在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"}] 

“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://sofzh.miximages.com/c%23/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"} 

有了这个,你再次得到你的七个class级。

现在,也许你想要对这些变化进行分类,无论白天。 如果同一个人每天在同一时间完成相同的任务,那么将它称为“星期一从10变为15”是没有用的,因为它也发生在Weds和Fridays(如我们的例子中)。

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

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

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

结果是

图片http://sofzh.miximages.com/c%23/mise9.png

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

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

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

结果是:

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

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

编辑:隔夜转移和标准化

如果你有(或计划有)从一天开始并在下面结束的轮class,那么建模更好

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

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

这是因为与任何统计方法一样,变量之间的相关性必须明确,否则方法会失败。 该原则可能会像“保持候选人数据规范化”之类的。 这两个概念几乎相同(属性应该是独立的)。

—编辑结束—

到现在为止,我猜你很清楚,如果分析,你可以用这种方式做什么。

一些参考

  1. 当然, 维基百科 ,其“参考”和“进一步阅读”都是很好的指南。
  2. 这里有一个很好的video,展示了Statsoft的function,但是你可以通过算法了解其他许多想法。
  3. 以下是所涉算法的基本解释
  4. 在这里你可以找到R for Cluster Analysis的令人印象深刻的function( R是一个非常好的选择)
  5. 最后, 在这里您可以找到一长串用于统计的免费和商业软件,包括群集。

HTH!

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

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

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

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

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