Что первое приходит в голову, когда вы слышите о «Process mining»? Я приставляю граф процесса, состоящий из n вершин и m ребер. Для чего он нужен? думаю все и так знаю, он помогает анализировать переходы между активностями. Все это замечательно, когда активностей и переходов мало, пример на рис.1

А если активностей больше 5? Количество возможных переходов возрастает, и граф становится сложно «читать». Для удобства анализа всех возможным переходов можно использовать «Слово процесса»
СП — это комбинации закодированных активностей лога, которая поможет вам при анализе бизнес процесса. Рассмотри далее, как составить такое «Слово». Возьму процесс формирования заявок, заявка должна пройти путь Черновик — На согласовании – Утвержден. Данные по заявкам я сохранила в csv файл, состоящий из 3 столбцов: ИД, Статут и Изменено.
Пример 1 заявки

Импортируем библиотеки pandas, itertools и string
import pandas as pd
from itertools import combinations
from string import ascii_uppercase as alphabet
Читаем лог в датафрейм, я еще переименовываю столбцы.
df = pd.read_csv('C:\\Users\\Golovataya-AM\\Desktop\\for ipr.csv', sep = ';', encoding = 'cp1251')
df = df.rename(columns = {'ИД':'id_column','Статус':'activity_column', 'Изменено': 'dt_column'})
df.head(3)
Теперь наш датафрейм выглядит так:

Считаем количество уникальных активностей (в нашем примере всего 3 активности — Черновик, на согласовании, утвержден) и записываем в список uniq_activ.
uniq_activ = df['activity_column'].unique()

Формируем список, состоящий из латинского алфавита. Для этого мы импортировали библиотеки string и itertools.
simbol = [''.join(item) for item in combinations(alphabet,1)]
После соединения списков uniq_activ и symbol получаем датафрей, содержащий символы и их расшифровки, т.е. уникальные активности заявки.
uniq_activ_encoder = pd.DataFrame({'activity_column':uniq_activ,'symbol':simbol[:len(uniq_activ)]})

Теперь можно джойнить фреймы df и uniq_activ_encoder, но не забываем сортировку по времени. Иначе «слово процесса» получиться неправильным, так как последовательность активностей будет нарушена.
df = df.merge(uniq_activ_encoder, on='activity_column',how='left').sort_values(by=['id_column','dt_column','activity_column'])

Добавляем разделитель “,” и схлопываем все значение из столбца ‘symbol_’ , группируя по ИД.
str.slice() нужен, чтобы удалить последнюю «запятую»
df['symbol_']=df['symbol']+','
df['process_word'] = df.groupby('id_column')['symbol_'].transform('sum').str.slice(stop=-1)
У нас получился датафрейм, содержащий ИД задачи и «Слово процесса», описывающее все шаги и их последовательность.
df[['id_column','process_word']].drop_duplicates().reset_index(drop=True)\

Внесем корректировки в наш скрипт. Сейчас мы анализируем процесс, состоящий из 3 действий. А если ваши задачи будут содержать 25 действий или 1500? Чтобы наше «Слово» работало с любым объемом активностей, расширим количество уникальных символов. Так как английский алфавит ограничен и содержит всего 26 букв, добавим комбинации, что позволит увеличить уникальные значения, например, до 17 576. Считаем количество действий и записываем в условие. Если активностей меньше 26, символ равен букве, если длина списка uniq_activ меньше 650, то создается комбинация.
if len(uniq_activ)<26:
simbol =[''.join(item) for item in alphabet]
elif len(uniq_activ)<650:
simbol=[''.join(item) for item in combinations(alphabet,2)]
else:
simbol =[''.join(item) for item in combinations(alphabet,3)]
Финальная версия СП.
import pandas as pd
from itertools import combinations
from string import ascii_uppercase as alphabet
df = pd.read_csv('C:\\Users\\...\\log.csv', sep = ';', encoding = 'cp1251')
df = df.rename(columns = {'ИД':'id_column','Активность':'activity_column', 'Дата: 'dt_column'})
uniq_activ = df['activity_column'].unique()
if len(uniq_activ)<26:
simbol =[''.join(item) for item in alphabet]
elif len(uniq_activ)<650:
simbol=[''.join(item) for item in combinations(alphabet,2)]
else:
simbol =[''.join(item) for item in combinations(alphabet,3)]
uniq_activ_encoder = pd.DataFrame({'activity_column':uniq_activ,'symbol':simbol[:len(uniq_activ)]})
df = df.merge(uniq_activ_encoder, on='activity_column',how='left').sort_values(by=['id_column','dt_column','activity_column'])
df['symbol_']=df['symbol']+','
df['process_word'] = df.groupby('id_column')['symbol_'].transform('sum').str.slice(stop=-1)
df[['id_column', 'process_word']].drop_duplicates()
Тестируем полученный скрипт на логе, с количеством уникальных активностей 36. Теперь каждая активность кодируется 2 буквами.

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