Python
Overzicht
De Python verrijking is een van de krachtigste en meest flexibele verrijkingsoperators in mindzieStudio, waarmee je eigen Python-code kunt schrijven om je process mining data te transformeren, analyseren en verrijken. Deze operator biedt directe toegang tot je eventloggegevens via Pandas DataFrames, waardoor je het volledige Python-ecosysteem kunt benutten, inclusief bibliotheken zoals NumPy, Pandas en eigen bedrijfslogica, om geavanceerde datatransformaties te creëren die verder gaan dan standaard verrijkingen.
Met een gebruiksfrequentie van 95% is Python een van de meest gebruikte verrijkingen in mindzieStudio. Het overbrugt de kloof tussen standaard process mining operaties en geavanceerde data science workflows, waardoor datawetenschappers en analisten aangepaste algoritmen, complexe bedrijfsregels en geavanceerde analyses direct binnen hun process mining pipeline kunnen toepassen. De operator integreert Python-code-executie naadloos met het datamodel van mindzieStudio, waarbij automatisch dataseialisatie, typeconversie en resultaatintegratie terug in je dataset worden afgehandeld.
Gebruik
- Bereken complexe KPI's die aangepaste bedrijfslogica vereisen die niet beschikbaar is in standaard calculators
- Pas machine learning modellen toe voor voorspelling, classificatie of clustering direct op procesdata
- Voer geavanceerde tekstverwerking en natural language processing uit op eventattributen
- Implementeer aangepaste conformance checks op basis van complexe bedrijfsregels
- Maak afgeleide attributen met statistische analyse en geavanceerde wiskundige bewerkingen
- Integreer externe databronnen door APIs aan te roepen of externe bestanden te lezen binnen Python-code
- Bouw aangepaste data kwaliteitscontroles en validatieregels specifiek voor jouw bedrijfsdomein
Instellingen
Filter: Optionele filter om te beperken welke cases door het Python-script worden verwerkt. Hiermee kun je bewerkingen alleen toepassen op specifieke subsets van je data, wat de prestaties verbetert en gerichte analyses mogelijk maakt. Zonder filter verwerkt de Python-code alle cases in de dataset.
Columns: Selecteer welke bestaande kolommen uit je dataset beschikbaar moeten worden gemaakt aan het Python-script. Deze kolommen zijn toegankelijk in de case_table en event_table DataFrames. Alleen geselecteerde kolommen worden naar Python doorgestuurd om het geheugenverbruik te minimaliseren en prestaties te verbeteren. De CaseId-kolom wordt altijd automatisch toegevoegd.
Change Columns: Geef aan welke van de geselecteerde kolommen door je Python-script mogen worden aangepast. Deze instelling stelt je in staat bestaande attribuutwaarden te updaten terwijl de dataintegriteit behouden blijft. Alleen kolommen die in Columns zijn geselecteerd, kunnen worden gewijzigd.
New Columns: Definieer nieuwe attributen die je Python-script zal creëren. Voor elke nieuwe kolom moet je opgeven:
- Kolomnaam: De interne naam gebruikt in Python-code
- Weergavenaam: De gebruikersvriendelijke naam getoond in mindzieStudio
- Gegevenstype: Het datatypesoort (String, Integer, DateTime, Boolean, Double)
- Bron Type: Of het attribuut op Case- of Eventniveau wordt toegevoegd
- Formaat: Optioneel weergevingsformaat voor het attribuut
Python Code: Het Python-script dat op je data wordt uitgevoerd. Je code heeft toegang tot:
case_table: Pandas DataFrame met case-level attributenevent_table: Pandas DataFrame met event-level data met kolommen voor InternalEventIndex, CaseId, ActivityName, ActivityTime en alle geselecteerde eventattributen
Het script dient deze DataFrames ter plekke te wijzigen. Wijzigingen in bestaande kolommen (gemarkeerd in Change Columns) of toevoegingen van nieuwe kolommen (gedefinieerd in New Columns) worden automatisch teruggevoerd in je dataset.
Python Image: Specificeert de Python uitvoeringsomgeving. Opties zijn onder andere:
- LOCAL: Gebruikt de lokale Python-installatie (indien beschikbaar)
- Docker image naam: Specifiek Docker image met benodigde Python-pakketten
- Default: mindzie’s standaard Python-omgeving met gangbare data science bibliotheken
Voorbeelden
Voorbeeld 1: Bereken Orderverwerkingsefficiëntiescore
Scenario: In een order-to-cash proces moet je een aangepaste efficiëntiescore berekenen op basis van orderwaarde, verwerkingstijd en aantal herstelactiviteiten.
Instellingen:
- Filter: Geen (verwerk alle cases)
- Columns: OrderValue, CustomerPriority
- Change Columns: Geen
- New Columns:
- Kolomnaam: EfficiencyScore
- Weergavenaam: Efficiency Score
- Gegevenstype: Double
- Bron Type: Case
- Python Code:
# Calculate efficiency score for each order
import numpy as np
# Count rework activities per case
rework_activities = ['Order Correction', 'Price Adjustment', 'Approval Retry']
event_table['IsRework'] = event_table['ActivityName'].isin(rework_activities)
rework_counts = event_table.groupby('CaseId')['IsRework'].sum().reset_index()
rework_counts.columns = ['CaseId', 'ReworkCount']
# Calculate case duration in days
case_durations = event_table.groupby('CaseId')['ActivityTime'].agg(['min', 'max'])
case_durations['Duration'] = (case_durations['max'] - case_durations['min']).dt.total_seconds() / 86400
case_durations = case_durations.reset_index()[['CaseId', 'Duration']]
# Merge with case table
case_table = case_table.merge(rework_counts, on='CaseId', how='left')
case_table = case_table.merge(case_durations, on='CaseId', how='left')
# Calculate efficiency score (0-100)
case_table['EfficiencyScore'] = 100 * (
(case_table['OrderValue'] / case_table['OrderValue'].max()) * 0.4 +
(1 - case_table['ReworkCount'] / 10) * 0.3 +
(1 - case_table['Duration'] / 30) * 0.3
)
case_table['EfficiencyScore'] = np.clip(case_table['EfficiencyScore'], 0, 100)
# Clean up temporary columns
case_table = case_table.drop(['ReworkCount', 'Duration'], axis=1)
- Python Image: LOCAL
Uitvoer: Maakt een nieuw case attribuut "Efficiency Score" met waarden van 0 tot 100, waarbij hogere scores duiden op efficiëntere orderverwerking op basis van een combinatie van orderwaarde, minimale herstelactiviteiten en snellere verwerkingstijd.
Inzichten: Deze aangepaste score helpt te identificeren welke orders het meest efficiënt worden verwerkt en kan worden gebruikt voor benchmarking, het identificeren van best practices en prioritering van procesverbetering.
Voorbeeld 2: Detecteer Abnormale Eventvolgordes
Scenario: In een zorgproces identificeer je cases waarbij de volgorde van medische procedures afwijkt van standaardprotocollen.
Instellingen:
- Filter: Geen
- Columns: PatientAge, Department
- Change Columns: Geen
- New Columns:
- Kolomnaam: HasAnomalousSequence
- Weergavenaam: Anomalous Sequence Detected
- Gegevenstype: Boolean
- Bron Type: Case
- Kolomnaam: AnomalyDescription
- Weergavenaam: Anomaly Description
- Gegevenstype: String
- Bron Type: Case
- Python Code:
# Define expected sequence patterns
normal_sequences = [
['Registration', 'Triage', 'Examination', 'Treatment', 'Discharge'],
['Registration', 'Triage', 'Examination', 'Lab Test', 'Treatment', 'Discharge'],
['Registration', 'Emergency Assessment', 'Treatment', 'Observation', 'Discharge']
]
def check_sequence_anomaly(group):
activities = group.sort_values('ActivityTime')['ActivityName'].tolist()
# Check for repeated activities
if len(activities) != len(set(activities)):
return True, "Repeated activities detected"
# Check for out-of-order activities
if 'Discharge' in activities and activities.index('Discharge') < len(activities) - 1:
return True, "Activities after discharge"
if 'Registration' in activities and activities.index('Registration') > 0:
return True, "Registration not first activity"
# Check if sequence matches any normal pattern
matches_normal = any(
all(act in activities for act in normal_seq)
for normal_seq in normal_sequences
)
if not matches_normal and len(activities) > 3:
return True, "Non-standard sequence pattern"
return False, ""
# Apply anomaly detection to each case
anomaly_results = event_table.groupby('CaseId').apply(check_sequence_anomaly)
# Add results to case table
case_table['HasAnomalousSequence'] = case_table['CaseId'].map(
lambda x: anomaly_results[x][0] if x in anomaly_results.index else False
)
case_table['AnomalyDescription'] = case_table['CaseId'].map(
lambda x: anomaly_results[x][1] if x in anomaly_results.index else ""
)
- Python Image: LOCAL
Uitvoer: Maakt twee nieuwe case attributen:
- "Anomalous Sequence Detected": Boolean flag die aangeeft of de case een ongebruikelijke volgorde heeft
- "Anomaly Description": Tekstuele beschrijving van de gedetecteerde anomalie
Inzichten: Deze verrijking helpt bij het identificeren van cases die afwijken van standaard medische protocollen, zodat kwaliteitszorgteams mogelijke problemen kunnen onderzoeken en patiënteveiligheid kunnen waarborgen.
Voorbeeld 3: Bereken Leveranciersprestatie Metrics
Scenario: In een inkoopproces bereken je uitgebreide leveranciersprestatiematen op basis van levertijden, kwaliteitsproblemen en volledigheid van orders.
Instellingen:
- Filter: ActivityName = "Goods Receipt"
- Columns: SupplierID, OrderQuantity, ReceivedQuantity
- Change Columns: Geen
- New Columns:
- Kolomnaam: OnTimeDeliveryRate
- Weergavenaam: On-Time Delivery Rate %
- Gegevenstype: Double
- Bron Type: Case
- Kolomnaam: QualityScore
- Weergavenaam: Supplier Quality Score
- Gegevenstype: Double
- Bron Type: Case
- Python Code:
# Calculate delivery performance
def calculate_supplier_metrics(group):
po_created = group[group['ActivityName'] == 'PO Created']['ActivityTime'].min()
goods_received = group[group['ActivityName'] == 'Goods Receipt']['ActivityTime'].max()
# Expected delivery time is 5 business days
expected_days = 5
actual_days = np.busday_count(po_created.date(), goods_received.date())
on_time = 1 if actual_days <= expected_days else 0
# Check for quality issues
has_quality_issue = 'Quality Issue' in group['ActivityName'].values
has_return = 'Return to Supplier' in group['ActivityName'].values
quality_score = 100
if has_quality_issue:
quality_score -= 30
if has_return:
quality_score -= 40
return pd.Series({
'OnTimeDelivery': on_time,
'QualityScore': quality_score
})
# Calculate metrics for each case
supplier_metrics = event_table.groupby('CaseId').apply(calculate_supplier_metrics)
# Aggregate by supplier
supplier_performance = case_table.merge(supplier_metrics, left_on='CaseId', right_index=True)
supplier_summary = supplier_performance.groupby('SupplierID').agg({
'OnTimeDelivery': 'mean',
'QualityScore': 'mean'
}).reset_index()
supplier_summary.columns = ['SupplierID', 'OnTimeDeliveryRate', 'AvgQualityScore']
# Add back to case table
case_table = case_table.merge(
supplier_summary[['SupplierID', 'OnTimeDeliveryRate', 'AvgQualityScore']],
on='SupplierID',
how='left'
)
case_table['OnTimeDeliveryRate'] = case_table['OnTimeDeliveryRate'] * 100
case_table.rename(columns={'AvgQualityScore': 'QualityScore'}, inplace=True)
- Python Image: LOCAL
Uitvoer: Maakt leveranciersprestatiematen op caseniveau:
- "On-Time Delivery Rate %": Percentage orders op tijd geleverd door deze leverancier
- "Supplier Quality Score": Kwaliteitsscore van 0-100 gebaseerd op kwaliteitsproblemen en retouren
Inzichten: Deze metrics stellen inkoopteams in staat om leveranciers objectief te evalueren, beslissingen over leveranciersselectie te ondersteunen en leveranciers te identificeren die verbeteringen nodig hebben.
Voorbeeld 4: Tekstmining op Procescommentaren
Scenario: In een IT-servicemanagementproces analyseer je ticketcommentaren om problemen te categoriseren en sentiment te detecteren.
Instellingen:
- Filter: Geen
- Columns: TicketDescription, ResolutionNotes
- Change Columns: Geen
- New Columns:
- Kolomnaam: IssueCategory
- Weergavenaam: Issue Category
- Gegevenstype: String
- Bron Type: Case
- Kolomnaam: CustomerSentiment
- Weergavenaam: Customer Sentiment
- Gegevenstype: String
- Bron Type: Case
- Python Code:
import re
# Define keywords for categorization
category_keywords = {
'Hardware': ['laptop', 'desktop', 'printer', 'mouse', 'keyboard', 'monitor', 'hardware'],
'Software': ['application', 'software', 'program', 'install', 'update', 'crash', 'error'],
'Network': ['network', 'internet', 'wifi', 'connection', 'vpn', 'firewall'],
'Access': ['password', 'login', 'access', 'permission', 'authentication', 'account'],
'Other': []
}
# Sentiment indicators
negative_words = ['slow', 'broken', 'failed', 'cannot', 'unable', 'frustrated', 'urgent', 'critical']
positive_words = ['resolved', 'working', 'fixed', 'thank', 'great', 'excellent', 'happy']
def categorize_issue(text):
if pd.isna(text):
return 'Other'
text_lower = text.lower()
for category, keywords in category_keywords.items():
if any(keyword in text_lower for keyword in keywords):
return category
return 'Other'
def analyze_sentiment(text):
if pd.isna(text):
return 'Neutral'
text_lower = text.lower()
negative_count = sum(1 for word in negative_words if word in text_lower)
positive_count = sum(1 for word in positive_words if word in text_lower)
if negative_count > positive_count:
return 'Negative'
elif positive_count > negative_count:
return 'Positive'
else:
return 'Neutral'
# Apply text analysis
case_table['IssueCategory'] = case_table['TicketDescription'].apply(categorize_issue)
case_table['CustomerSentiment'] = case_table['TicketDescription'].apply(analyze_sentiment)
- Python Image: LOCAL
Uitvoer: Maakt twee tekstafgeleide attributen:
- "Issue Category": Categorisatie van het IT-probleem (Hardware, Software, Network, Access, Other)
- "Customer Sentiment": Sentimentanalyse resultaat (Positive, Negative, Neutral)
Inzichten: Deze verrijking stelt IT-servicemanagers in staat inzicht te krijgen in probleemverdeling, prioriteit te geven op basis van klantgevoel, en gebieden te identificeren die extra ondersteuning of training nodig hebben.
Voorbeeld 5: Financiële Compliance Risicoscore
Scenario: In een proces voor goedkeuring van financiële transacties bereken je een compliance risicoscore op basis van meerdere risicofactoren.
Instellingen:
- Filter: TransactionType = "Wire Transfer"
- Columns: TransactionAmount, CustomerCountry, AccountAge, PreviousFlags
- Change Columns: Geen
- New Columns:
- Kolomnaam: ComplianceRiskScore
- Weergavenaam: Compliance Risk Score
- Gegevenstype: Integer
- Bron Type: Case
- Kolomnaam: RiskLevel
- Weergavenaam: Risk Level
- Gegevenstype: String
- Bron Type: Case
- Python Code:
# Define risk factors and weights
high_risk_countries = ['Country1', 'Country2', 'Country3'] # Placeholder for actual list
suspicious_amount_threshold = 10000
rapid_transaction_threshold = 5 # transactions per day
def calculate_risk_score(row):
risk_score = 0
# Amount risk (0-30 points)
if row['TransactionAmount'] > suspicious_amount_threshold:
risk_score += min(30, int(row['TransactionAmount'] / suspicious_amount_threshold * 10))
# Geographic risk (0-25 points)
if row['CustomerCountry'] in high_risk_countries:
risk_score += 25
# Account age risk (0-20 points)
if pd.notna(row['AccountAge']) and row['AccountAge'] < 30:
risk_score += 20 - int(row['AccountAge'] / 30 * 20)
# Previous flags risk (0-25 points)
if pd.notna(row['PreviousFlags']) and row['PreviousFlags'] > 0:
risk_score += min(25, row['PreviousFlags'] * 5)
return risk_score
# Calculate transaction velocity
transaction_counts = event_table[event_table['ActivityName'] == 'Transaction Initiated'].groupby('CaseId').size()
case_table['TransactionVelocity'] = case_table['CaseId'].map(transaction_counts).fillna(0)
# Calculate risk scores
case_table['ComplianceRiskScore'] = case_table.apply(calculate_risk_score, axis=1)
# Assign risk levels
def assign_risk_level(score):
if score >= 70:
return 'High'
elif score >= 40:
return 'Medium'
else:
return 'Low'
case_table['RiskLevel'] = case_table['ComplianceRiskScore'].apply(assign_risk_level)
# Clean up temporary columns
case_table = case_table.drop(['TransactionVelocity'], axis=1)
- Python Image: LOCAL
Uitvoer: Maakt uitgebreide risicobeoordelingsattributen:
- "Compliance Risk Score": Numerieke risicoscore van 0-100
- "Risk Level": Categorische risicoclassificatie (High, Medium, Low)
Inzichten: Deze risicoscore stelt compliance teams in staat transacties prioriteit te geven, goedkeuringsworkflows te automatiseren op basis van risiconiveaus, en naleving van regelgeving te waarborgen met minimale false positives.
Output
De Python verrijkingsoperator produceert nieuwe of aangepaste attributen gebaseerd op je aangepaste code:
Nieuwe Case Attributen: Alle kolommen die worden toegevoegd aan de case_table DataFrame en matchen met de gedefinieerde New Columns worden als case-level attributen in je dataset aangemaakt. Deze attributen zijn direct beschikbaar voor gebruik in filters, calculators en andere verrijkingen.
Nieuwe Event Attributen: Alle kolommen die worden toegevoegd aan de event_table DataFrame en matchen met de gedefinieerde New Columns worden als event-level attributen aangemaakt. Deze kunnen event-specifieke berekeningen of classificaties bevatten.
Aangepaste Attributen: Bestaande kolommen die zijn opgegeven in Change Columns kunnen worden bijgewerkt. Het oorspronkelijke datatype moet behouden blijven, maar waarden kunnen worden getransformeerd volgens je bedrijfslogica.
Datatype Handling: De operator behandelt automatisch typeconversie tussen Python en mindzieStudio datatypes:
- Python strings → mindzieStudio String
- Python int32/int64 → mindzieStudio Integer
- Python float → mindzieStudio Double
- Python datetime → mindzieStudio DateTime
- Python bool → mindzieStudio Boolean
Case en Event Verwijdering: Geavanceerd gebruik maakt het mogelijk cases of events te verwijderen door ze uit de respectievelijke DataFrames te filteren. Cases die niet in de output case_table voorkomen worden uit de dataset verwijderd.
De verrijkte attributen integreren naadloos met alle andere mindzieStudio functies, wat je in staat stelt aangepaste Python-transformaties door je volledige process mining analyse workflow heen te gebruiken.
Zie ook
- AI Case Prediction - Gebruik machine learning modellen voor voorspelling
- Attribute Calculator - Maak eenvoudige afgeleide attributen zonder code
- Filter Cases - Filter data voorafgaand aan verwerking
- Representative Case Attribute - Extraheer representatieve waarden uit events
Deze documentatie maakt deel uit van het mindzie Studio process mining platform.