Создайте сводное описание расписания с учетом списка смен - PullRequest
5 голосов
/ 02 июля 2010

Предполагая, что у меня есть список смен для события (в формате дата / время начала, дата / время окончания) - есть ли какой-нибудь алгоритм, который я мог бы использовать для создания обобщенного резюме графика? Для большинства смен характерна частая повторяемость (например, по понедельникам с 9:00 до 13:00, по вторникам с 10:00 до 15:00 и т. Д.). Однако могут быть (и будут) исключения из этого правила (например, одна из смен выпала на выходной и была перенесена на следующий день). Было бы неплохо исключить их из моего «резюме», поскольку я хочу дать более общий ответ о том, когда это событие обычно происходит.

Полагаю, я ищу какой-то статистический метод для определения дня и времени и создания описания на основе наиболее частых случаев, встречающихся в списке. Есть ли какой-то общий алгоритм для чего-то подобного? Кто-нибудь создал нечто подобное?

В идеале я ищу решение на C # или VB.NET, но не против портировать с любого другого языка.

Заранее спасибо!

Ответы [ 4 ]

11 голосов
/ 15 июля 2010

Вы можете использовать Кластерный анализ .

Кластеризация - это способ разделения набора данных на похожие компоненты (подмножества). Концепция «сходства» предполагает некоторое определение «расстояния» между точками. Существует много обычных формул для расстояния, в том числе обычное евклидово расстояние.

Практический кейс

Прежде чем указать вам на причину сделки, давайте покажем практический пример вашей проблемы, чтобы вы могли принять участие в алгоритмах и пакетах или отказаться от них заранее.

Для простоты я смоделировал проблему в Mathematica, потому что Cluster Analysis включен в программное обеспечение и очень прост в настройке.

Сначала сгенерируйте данные. Формат: {ДЕНЬ, ВРЕМЯ НАЧАЛА, ВРЕМЯ КОНЦА}.
Для времени начала и окончания добавлена ​​случайная величина (+ полчаса, ноль, -полчаса}, чтобы показать способность алгоритма справляться с "шумом".

Есть три дня, три смены в день и одна дополнительная (последняя) «аномальная» смена, которая начинается в 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"}]

«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"}]  

И результат:

альтернативный текст 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», потому что это происходит также по субботам и пятницам (как в нашем примере).

Давайте проанализируем данные без учета первого столбца:

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

В этом случае мы не выбираем количество кластеров для извлечения, оставляя решение за пакетом.

Результат

изображение 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. Конечно, Википедия , ее "ссылки" и "дальнейшее чтение" являются хорошим руководством.
  2. Хорошее видео здесь , показывающее возможности Statsoft, но вы можете получить много идей о других вещах, которые вы можете сделать с помощью алгоритма.
  3. Здесь - основное объяснение задействованных алгоритмов
  4. Здесь вы можете найти впечатляющую функциональность R для ClusterАнализ ( R - ОЧЕНЬ хороший вариант)
  5. Наконец, здесь вы можете найти длинный список бесплатных и коммерческих программ для статистики в целом, включая кластеризацию.

HTH!

1 голос
/ 13 июля 2010

Я не думаю, что какой-либо готовый алгоритм существует, поэтому, к сожалению, вам нужно что-то придумать самостоятельно.Так как проблема не очень хорошо определена (с математической точки зрения), она потребует тестирования некоторых «реальных» данных, которые были бы достаточно репрезентативными, и небольшого изменения.

Я бы начал с деления ваших смен набудние дни (потому что, если я правильно понимаю, вы после еженедельного просмотра) - поэтому для каждого дня недели у нас есть смены, которые происходят в этот день.Затем для каждого дня я бы группировал сдвиги, которые происходят в одно и то же время (или «примерно» в одно и то же время), здесь вам нужно придумать некоторую эвристику, то есть время начала и окончания не отклоняется от среднего значения в группе наболее 15 минут или 30 минут).Теперь нам нужна другая эвристика, чтобы решить, является ли эта группа релевантной, то есть, если сдвиг в 13:00 - 13:00 в понедельник произошел только один раз, когда он, вероятно, не актуален, но если это произошло по крайней мере в 70% понедельников, охватываемых данными, тоСоответствующий.И теперь ваши соответствующие группы для каждого дня недели будут составлять расписание, за которым вы следите.

0 голосов
/ 14 июля 2010

Один из вариантов - пометить все времена начала как +1, а времена окончания - как -1, а затем создать таблицу с тремя столбцами времени (как начало, так и конец), метку (+1 или -1) и число персонал в это время (начинается с нуля и добавляет или вычитает персонал, используя метку) и сортирует все в порядке времени.

Этот временной ряд теперь является кратким дескриптором уровня ваших сотрудников, и ярлыки также являются сериями. Теперь вы можете применять статистику временных рядов к обоим для поиска дневных, недельных или месячных паттернов.

0 голосов
/ 02 июля 2010

Можем ли мы увидеть пример набора данных?Если это действительно «чистые» данные, то вы можете просто найти режим времени начала и окончания.

...