03 / READY FOR REVIEWTrace the flag. Review the record.
Illustrative workflow · simulated transactions
IMPLEMENTEDPython + pandas
STRUCTURE3 focused scripts
DATASimulated CSV batch
APPROACHExplicit rule logic
01 / THE IDEA
Make the exceptions easier to inspect.
Before an analyst can interpret an unusual transaction, the underlying data needs to be usable. Missing amounts, duplicated rows, and inconsistent formats can obscure the story.
This demo breaks the work into three readable stages: prepare the records, apply a transparent decision, and summarise what needs review. A flag is a prompt for investigation, not proof of fraud.
Where SQL fits
SQL supports the wider investigation skill set: checking completeness, reconciling counts, and grouping records. The supplied implementation is Python/pandas and CSV; no SQL query or database integration was provided for this demo.
02 / HOW IT WORKS
One batch. Three deliberate steps.
Each script writes the file the next script reads. Run order matters; orchestration is a future extension.
INPUTtransactions.csvSimulated records
01 / CLEANclean_data.pyPrepare the dataset
02 / DETECTanalyze_data.pyCalculate and flag
03 / REPORTreport.pySummarise for review
01 DATA QUALITY
Start with cleaner inputs.
Standardise column names, remove exact duplicate rows, and coerce dates and amounts into usable types.
Mark missing or invalid amounts before median imputation.
Drop null transaction IDs, customer IDs, and merchants.
Keep positive amounts; sort by customer and date.
What the cleaning does not guarantee
Invalid dates become missing dates (NaT) and are not removed. Blank strings are not explicitly normalised. Duplicates are removed across full rows, not by transaction ID. If every amount is missing, the median cannot fill them.
→ cleaned_data.csv
02 ANOMALY LOGIC
Give every flag a reason.
Calculate each customer’s mean amount across the loaded cleaned batch. Compare each transaction with that baseline.
Spend spike: amount > 2 × customer mean.
High value: amount > ₹20,000.
Merchant match: exact match to a demo list.
The demo list contains Apple and Dell as arbitrary examples. It is not an assessment of those businesses.
→ anomalies.csv
03 REPORTING
Make the review manageable.
For a non-empty flagged set, calculate transaction count, distinct customers, total amount, and mean amount.
Print leading merchants by flag count.
Print leading customers by flagged spend.
Write the four summary metrics to CSV.
How an empty result behaves
The script prints a no-anomalies message and skips writing the summary CSV. Existing summary files are not cleared by the supplied code.
→ daily_anomaly_summary.csv
03 / INSIDE THE DECISION
Three checks. One combined decision.
A spend spike alone triggers a flag. Otherwise, both a high value and a merchant-list match are required. High value alone does not trigger the final flag.
Spend spikeOR(High value AND Merchant match)
INTERACTIVE EXPLANATION
Follow one transaction.
Choose an example to see how the same decision plays out.
Fixed examples, not an execution of the Python pipeline. Baselines shown are assumed batch means.
A baseline limitation worth showing.
The current transaction is included in its customer’s batch mean. This is not a historical-only or rolling baseline, so a large amount can raise its own comparison threshold. Both amount comparisons use strict “greater than”; equality does not pass.
THE IMPLEMENTATION
The Python behind the pipeline.
The three code excerpts supplied for this demo, with formatting restored for readability. They use pandas as pd; the excerpts omit the import and assume the input files and output folder already exist.
Original comments and output labels are retained. “Company logic” labels this illustrative decision; it does not establish Deloitte ownership. “High-risk” merchant labels and “amount at risk” are demo terminology, not verified risk assessments or losses.
clean_data.py
# 1. Load raw data
df = pd.read_csv('../data/transactions.csv')
# 2. Standardize column names
df.columns = df.columns.str.lower().str.strip()
# 3. Remove exact duplicate rows
df = df.drop_duplicates()
# 4. Convert date column to datetime
df['date'] = pd.to_datetime(df['date'], errors='coerce')
# 5. Handle missing or invalid amounts
df['amount'] = pd.to_numeric(df['amount'], errors='coerce')
df['amount_was_missing'] = df['amount'].isna()
median_amount = df['amount'].median()
df['amount'] = df['amount'].fillna(median_amount)
# 6. Remove transactions with missing critical identifiers
df = df.dropna(subset=['transaction_id', 'customer_id', 'merchant'])
# 7. Remove negative or zero-value transactions
df = df[df['amount'] > 0]
# 8. Sort for consistency (audit-friendly)
df = df.sort_values(by=['customer_id', 'date'])
# 9. Save cleaned data
df.to_csv('../output/cleaned_data.csv', index=False)
# 1. Load anomaly data
df = pd.read_csv('../output/anomalies.csv')
# 2. Handle case where no anomalies exist
if df.empty:
print("No anomalies detected for this period.")
else:
# 3. Summary metrics
total_anomalies = len(df)
unique_customers = df['customer_id'].nunique()
total_amount = df['amount'].sum()
avg_anomaly_amount = df['amount'].mean()
print(f"Total flagged transactions : {total_anomalies}")
print(f"Unique customers impacted : {unique_customers}")
print(f"Total amount at risk (₹) : {total_amount:,.2f}")
print(f"Average anomaly amount : {avg_anomaly_amount:,.2f}")
# 4. Top risky merchants
print("\nTop merchants by anomaly count:")
print(df['merchant'].value_counts().head())
# 5. Top customers by total anomaly spend
print("\nTop customers by anomaly spend:")
print(
df.groupby('customer_id')['amount']
.sum()
.sort_values(ascending=False)
.head()
)
# 6. Save daily summary
summary_df = pd.DataFrame([{
'total_anomalies': total_anomalies,
'unique_customers': unique_customers,
'total_amount_at_risk': total_amount,
'average_anomaly_amount': avg_anomaly_amount
}])
summary_df.to_csv('../output/daily_anomaly_summary.csv', index=False)
04 / WHAT COMES OUT
A useful handoff, not a black box.
01 / CSV
Cleaned records
cleaned_data.csv
Retained rows with standardised fields and an amount-missing indicator.
02 / CSV
Flagged transactions
anomalies.csv
Flagged rows retain the customer mean and individual rule columns.
03 / CONDITIONAL CSV
Batch summary
daily_anomaly_summary.csv
Four aggregate metrics when flags exist. The filename says “daily”; the script does not filter by day.
+ Console output adds the summary and top merchants/customers. This is a reporting channel, not a fourth output file. Flagged amounts are review totals, not confirmed financial losses.
05 / REFLECTION
The next layer is reliability.
The value of this foundation is its inspectability: each transformation and decision can be explained. Moving toward production would require more than adding detection rules.
Stronger input contractsSchema checks, invalid-date handling, and explicit rejection logs.
Better baselinesPrior-period comparisons and evaluation of false positives.
Repeatable operationsTests, scheduling, logs, and fresh empty-result outputs.
BUILT TO BE UNDERSTOOD
Clean the data. Explain the exception.
A small example of turning analytical work into a reviewable process.