Process mining, Анализ процессов

Реализация алгоритма 6 sigm для Рrocess Мining.

Время прочтения: 2 мин.

При исследовании процесса методами Process Mining одним из важнейших методов оценки процесса является концепция 6 sigm. В этой статье я хочу рассказать об одном из возможных вариантов реализации этого алгоритма на языке python. Ставим задачу: «Необходимо получить идентификаторы событий, которые выходят за рамки 6 sigm процесса».

Для решения поставленной задачи необходимо рассчитать несколько величин на основании лога процесса. Вспомним несколько терминов из статистики и используем формулу среднеквадратического отклонения

Приступим к написанию кода, для реализации. Для начала создадим из имеющегося лога датафрейм, он будет содержать идентификатор (id_column), время события (dt_column) и наименование события (activity_column).

six_sigm = pd.DataFrame(columns=['id_column', 'activity_column', ' dt_column'])

Рассмотрим случай, когда на вход функции не подаются параметры и мы хотим получить события, весь путь которых превышает 6 сигм. def six_sigm(eges=None):

        if (edges == None):

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

            six_sigm['max_time'] = six_sigm.groupby(‘id_column’)[‘dt_column’].transform('max')
            six_sigm['min_time'] = six_sigm.groupby(‘id_column’)[‘dt_column’].transform('min')
            six_sigm['delta']=(pd.to_datetime(six_sigm['max_time'])-pd.to_datetime(six_sigm['min_time'])).astype('timedelta64[s]')

Оставляем в датафрейме только уникальные значения идентификаторов и дельты времени.

  six_sigm=six_sigm[['id_column','delta']].drop_duplicates()

Считаем количество событий и подставляем в формулу среднеквадратического отклонения.

            six_sigm['time_mean']=six_sigm['delta'].sum()/six_sigm['delta'].count()
            six_sigm['x-Xmean2']=(six_sigm['delta']-six_sigm['time_mean'])**2
            SIGMA=(six_sigm['x-Xmean2'].sum()/(six_sigm['delta'].count()-1))**0.5

Так как наш процесс не имеет нормального распределения, после того как мы получили среднеквадратическое отклонение, умножаем его на 6 и фильтруем датафрейм.

            f_sigm=SIGMA*6
            six_sigm=six_sigm[six_sigm['delta']>f_sigm][['id_column']].reset_index(drop=True)
            return six_sigm

Теперь рассмотрим случай, когда мы хотим выделить события, в которых определенные переходы (ребра) превышают параметр 6 сигм.   Выполняем те же действия, только введем параметр edges=[(‘Stage1’,’Stage2’)] и при вычислениях будем ориентироваться на это ребро или, если это необходимо, список ребер.

else:
            six_sigm['activity_end'] = six_sigm.groupby(‘id_column’)[‘activity_column’].shift(-1)
            six_sigm['time_end'] = six_sigm.groupby(‘id_column’)[‘dt_column’].shift(-1)
            six_sigm['count'] = six_sigm.groupby(‘id_column’)[‘dt_column’].transform('count')
            six_sigm = six_sigm[six_sigm['count']!=1]
            six_sigm['activity_end'].fillna('end', inplace=True)
            six_sigm.loc[six_sigm['activity_end']=='end','time_end']=six_sigm.loc[six_sigm['activity_end']=='end','time_start']
            six_sigm['delta']=(pd.to_datetime(six_sigm['time_end'])-pd.to_datetime(six_sigm['time_start'])).astype('timedelta64[s]')
            six_sigm=six_sigm[six_sigm['activity_end']!='end']
            six_sigm=six_sigm.loc[six_sigm[['activity_start', 'activity_end']].apply(tuple, 1).isin(
                                pd.DataFrame(edges, columns=['activity_start', 'activity_end']).apply(tuple, 1))]
            six_sigm['time_mean']=six_sigm['delta'].sum()/six_sigm['delta'].count()
            six_sigm['x-Xmean2']=(six_sigm['delta']-six_sigm['time_mean'])**2
            SIGMA=(six_sigm['x-Xmean2'].sum()/(six_sigm['delta'].count()-1))**0.5
            f_sigm=SIGMA*6
            six_sigm=six_sigm[six_sigm['delta']>f_sigm][['id_column']].reset_index(drop=True).drop_duplicates()
            return six_sigm

На выходе эта функция вернет идентификаторы событий, превышающих 6 сигм процесса по полной длине события или по выбранным ребрам.

Советуем почитать