Создайте сводное описание расписания, учитывая список сдвигов

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

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

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

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

5
задан pmr 1 May 2012 в 17:55
поделиться

4 ответа

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

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

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

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

Для простоты я смоделировал проблему в системе 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"}]

«Агломерат» и «Связь» -> «Завершить» "- это два варианта тонкой настройки методов кластеризации, реализованных в системе 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

Где вы можете четко видеть наши семь кластеров.

Это решает часть вашей проблемы: идентификация данных. Теперь вы также хотите иметь возможность маркировать его.

Итак, мы возьмем каждый кластер и возьмем средние (округленные):

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

HTH!

12
ответ дан 18 December 2019 в 14:42
поделиться

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

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

1
ответ дан 18 December 2019 в 14:42
поделиться

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

0
ответ дан 18 December 2019 в 14:42
поделиться

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

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

0
ответ дан 18 December 2019 в 14:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: