عملية التعدين بدون PM4PY





من السهل جدًا إنشاء رسم بياني من سجلات العملية. يمتلك المحللون حاليًا تحت تصرفهم مجموعة متنوعة كافية من التطورات المهنية ، مثل Celonis و Disco و PM4PY و ProM وما إلى ذلك ، المصممة لتسهيل دراسة العمليات. من الصعب للغاية العثور على الانحرافات في الرسوم البيانية ، لاستخلاص النتائج الصحيحة منها.



ماذا لو كانت بعض التطورات المهنية التي أثبتت جدواها وذات أهمية خاصة غير متوفرة لسبب أو لآخر ، أو تريد المزيد من الحرية في الحسابات عند العمل مع الرسوم البيانية؟ ما مدى صعوبة كتابة عامل منجم بنفسك وتنفيذ بعض الإمكانات اللازمة للعمل مع الرسوم البيانية؟ سنفعل ذلك عمليًا باستخدام مكتبات Python القياسية ، وننفذ الحسابات ونقدم ، بمساعدتهم ، إجابات للأسئلة التفصيلية التي قد تهم مالكي العملية.



أود أن أبدي تحفظًا على الفور بأن الحل الوارد في المقالة ليس تنفيذًا صناعيًا. هذه بعض المحاولات لبدء العمل مع السجلات بنفسك بمساعدة كود بسيط يعمل بشكل مفهوم ، وبالتالي يجعل من السهل تكييفه. لا ينبغي استخدام هذا الحل في البيانات الضخمة ؛ فهذا يتطلب تحسينًا كبيرًا ، على سبيل المثال ، باستخدام حسابات المتجهات أو عن طريق تغيير نهج جمع وتجميع المعلومات حول الأحداث.



قبل إنشاء الرسم البياني ، تحتاج إلى إجراء العمليات الحسابية. سيكون الحساب الفعلي للرسم البياني هو نفس عامل التعدين المذكور سابقًا. لإجراء الحساب ، من الضروري جمع المعرفة حول الأحداث - رؤوس الرسم البياني والوصلات بينها وتدوينها ، على سبيل المثال ، في الكتب المرجعية. تمتلئ المراجع باستخدام إجراء الحساب ( رمز على github). يتم تمرير المراجع المكتملة كمعلمات لإجراء رسم الرسوم البيانية (انظر الكود من الرابط أعلاه). يقوم هذا الإجراء بتنسيق البيانات كما هو موضح أدناه:



digraph f {"Permit SUBMITTED by EMPLOYEE (6255)" -> "Permit APPROVED by ADMINISTRATION (4839)" [label=4829 color=black penwidth=4.723857205400346] 
"Permit SUBMITTED by EMPLOYEE (6255)" -> "Permit REJECTED by ADMINISTRATION (83)" [label=83 color=pink2 penwidth=2.9590780923760738] 
"Permit SUBMITTED by EMPLOYEE (6255)" -> "Permit REJECTED by EMPLOYEE (231)" [label=2 color=pink2 penwidth=1.3410299956639813] 
start [color=blue shape=diamond] 
end [color=blue shape=diamond]}


ويمررها إلى محرك رسومات Graphviz لتقديمها.



لنبدأ في بناء الرسوم البيانية وفحصها باستخدام عامل التعدين المنفذ. سنكرر إجراءات قراءة البيانات وفرزها وحساب الرسوم البيانية ورسمها كما في الأمثلة أدناه. على سبيل المثال ، يتم أخذ سجلات الأحداث من الإعلانات الدولية من مسابقة BPIC2020. رابط المنافسة.



نقرأ البيانات من السجل ونفرزها حسب التاريخ والوقت. تم تحويل تنسيق xes مسبقًا إلى .xlsx.



df_full = pd.read_excel('InternationalDeclarations.xlsx')
df_full = df_full[['id-trace','concept:name','time:timestamp']]
df_full.columns = ['case:concept:name', 'concept:name', 'time:timestamp']
df_full['time:timestamp'] = pd.to_datetime(df_full['time:timestamp'])
df_full = df_full.sort_values(['case:concept:name','time:timestamp'], ascending=[True,True])
df_full = df_full.reset_index(drop=True)


دعونا نحسب الرسم البياني.



dict_tuple_full = calc(df_full)


لنرسم الرسم البياني.



draw(dict_tuple_full,'InternationalDeclarations_full')


بعد الانتهاء من الإجراءات ، نحصل على الرسم البياني للعملية:







نظرًا لأن الرسم البياني الناتج غير قابل للقراءة ، فإننا نبسطه.



توجد عدة طرق لتحسين إمكانية القراءة أو تبسيط الرسم البياني:



  1. استخدام التصفية حسب أوزان الرؤوس أو الروابط ؛
  2. تخلص من الضوضاء
  3. أحداث المجموعة حسب تشابه الاسم.


لنأخذ النهج 3.



لنقم بإنشاء قاموس لدمج الأحداث:



_dict = {'Permit SUBMITTED by EMPLOYEE': 'Permit SUBMITTED',
 'Permit APPROVED by ADMINISTRATION': 'Permit APPROVED',
 'Permit APPROVED by BUDGET OWNER': 'Permit APPROVED',
 'Permit APPROVED by PRE_APPROVER': 'Permit APPROVED',
 'Permit APPROVED by SUPERVISOR': 'Permit APPROVED',
 'Permit FINAL_APPROVED by DIRECTOR': 'Permit FINAL_APPROVED',
 'Permit FINAL_APPROVED by SUPERVISOR': 'Permit FINAL_APPROVED',
 'Start trip': 'Start trip',
 'End trip': 'End trip',
 'Permit REJECTED by ADMINISTRATION': 'Permit REJECTED',
 'Permit REJECTED by BUDGET OWNER': 'Permit REJECTED',
 'Permit REJECTED by DIRECTOR': 'Permit REJECTED',
 'Permit REJECTED by EMPLOYEE': 'Permit REJECTED',
 'Permit REJECTED by MISSING': 'Permit REJECTED',
 'Permit REJECTED by PRE_APPROVER': 'Permit REJECTED',
 'Permit REJECTED by SUPERVISOR': 'Permit REJECTED',
 'Declaration SUBMITTED by EMPLOYEE': 'Declaration SUBMITTED',
 'Declaration SAVED by EMPLOYEE': 'Declaration SAVED',
 'Declaration APPROVED by ADMINISTRATION': 'Declaration APPROVED',
 'Declaration APPROVED by BUDGET OWNER': 'Declaration APPROVED',
 'Declaration APPROVED by PRE_APPROVER': 'Declaration APPROVED',
 'Declaration APPROVED by SUPERVISOR': 'Declaration APPROVED',
 'Declaration FINAL_APPROVED by DIRECTOR': 'Declaration FINAL_APPROVED',
 'Declaration FINAL_APPROVED by SUPERVISOR': 'Declaration FINAL_APPROVED',
 'Declaration REJECTED by ADMINISTRATION': 'Declaration REJECTED',
 'Declaration REJECTED by BUDGET OWNER': 'Declaration REJECTED',
 'Declaration REJECTED by DIRECTOR': 'Declaration REJECTED',
 'Declaration REJECTED by EMPLOYEE': 'Declaration REJECTED',
 'Declaration REJECTED by MISSING': 'Declaration REJECTED',
 'Declaration REJECTED by PRE_APPROVER': 'Declaration REJECTED',
 'Declaration REJECTED by SUPERVISOR': 'Declaration REJECTED',
 'Request Payment': 'Request Payment',
 'Payment Handled': 'Payment Handled',
 'Send Reminder': 'Send Reminder'}


دعنا نجمع الأحداث ونرسم الرسم البياني للعملية مرة أخرى.



df_full_gr = df_full.copy()
df_full_gr['concept:name'] = df_full_gr['concept:name'].map(_dict)
dict_tuple_full_gr = calc(df_full_gr)
draw(dict_tuple_full_gr,'InternationalDeclarations_full_gr'




بعد تجميع الأحداث حسب تشابه الاسم ، تحسنت سهولة قراءة الرسم البياني. دعنا نحاول العثور على إجابات للأسئلة. رابط إلى قائمة الأسئلة. على سبيل المثال ، كم عدد التصريحات التي لم يسبقها تصريح معتمد مسبقًا؟



للإجابة على السؤال المطروح ، نقوم بتصفية الرسم البياني حسب الأحداث ذات الأهمية ونرسم الرسم البياني للعملية مرة أخرى.



df_full_gr_f = df_full_gr[df_full_gr['concept:name'].isin(['Permit SUBMITTED',
                                                            'Permit APPROVED',
                                                            'Permit FINAL_APPROVED',
                                                            'Declaration FINAL_APPROVED',
                                                            'Declaration APPROVED'])]
df_full_gr_f = df_full_gr_f.reset_index(drop=True)
dict_tuple_full_gr_f = calc(df_full_gr_f)
draw(dict_tuple_full_gr_f,'InternationalDeclarations_full_gr_isin')






بمساعدة الرسم البياني الناتج ، يمكننا بسهولة تقديم إجابة على السؤال المطروح - لم يسبق تصريح معتمد مسبقًا 116 و 312 إعلانًا.



يمكنك أيضًا "فشل" (التصفية حسب "الحالة: المفهوم: الاسم" ، والمشاركة في الاتصال المطلوب) للوصلات 116 و 312 وتأكد من عدم وجود أحداث متعلقة بالأذونات على الرسوم البيانية.



دعونا "نفشل" في الاتصال 116:



df_116 = df_full_gr_f[df_full_gr_f['case:concept:name'].isin(d_case_start2['Declaration FINAL_APPROVED'])]
df_116 = df_116.reset_index(drop=True)
dict_tuple_116 = calc(df_116)
draw(dict_tuple_116,'InternationalDeclarations_full_gr_isin_116')






دعنا "نفشل" للاتصال 312:



df_312 = df_full_gr_f[df_full_gr_f['case:concept:name'].isin(d_case_start2['Declaration APPROVED'])]
df_312 = df_312.reset_index(drop=True)
dict_tuple_312 = calc(df_312)
draw(dict_tuple_312,'InternationalDeclarations_full_gr_isin_312')






نظرًا لعدم وجود أحداث متعلقة بالأذونات على الرسوم البيانية المستلمة ، تم تأكيد صحة الإجابات 116 و 312.



كما ترى ، فإن كتابة عامل منجم وتنفيذ القدرات اللازمة للعمل مع الرسوم البيانية ليست مهمة صعبة ، والتي نجحت الوظائف المدمجة في Python و Graphviz في التعامل معها كمحرك رسومات.



All Articles