Table of Contents

Introduction

In banking systems, patterns reveal truth—and few patterns are as telling as the mode: the most frequently occurring value in a dataset. While averages smooth out anomalies, the mode highlights repetition, making it a powerful tool for spotting fraud, system errors, or policy violations. This guide shows you how to compute the mode correctly and efficiently in Python—with a real-world banking use case, robust error handling, and zero tolerance for bugs.

What Is the Mode—and Why Banks Care

The mode is the value that appears most often in a list. A dataset can have:

In banking, the mode helps detect:

Unlike mean or median, the mode exposes behavioral repetition—exactly what fraud analysts need.

Core Methods to Compute the Mode in Python

1. Using statistics.mode() (Simple but Limited)

Code
import statistics

try:
    mode_val = statistics.mode(data)
except statistics.StatisticsError:
    mode_val = None  # No unique mode

Built-in and clean—but fails if there’s no single mode.

2. Manual Counting with collections.Counter (Robust & Flexible)

Code
from collections import Counter

def find_mode(arr):
    if not arr:
        return None
    counts = Counter(arr)
    max_count = max(counts.values())
    modes = [k for k, v in counts.items() if v == max_count]
    return modes[0] if len(modes) == 1 else modes  # Return single or list

Handles multimodal data, empty inputs, and custom logic.

Real-World Scenario: Detecting Suspicious Transaction Amounts

Problem

Your bank’s fraud detection system logs transaction amounts. You notice many transactions of $49.99—is this a pricing pattern or a red flag?

Goal

Find the most frequent transaction amount in the last hour to flag potential testing behavior by fraudsters.

Requirements

Time and Space Complexity

Avoid sorting-based approaches—they’re slower (O(n log n)) and unnecessary.

Complete, Production-Ready Implementation

Code
from collections import Counter
from typing import List, Union, Optional

def get_transaction_mode(amounts: List[Union[int, float]]) -> Optional[Union[float, List[float]]]:
    """
    Find the mode(s) of transaction amounts for fraud detection.
    
    Args:
        amounts: List of transaction amounts (e.g., [49.99, 9.99, 49.99, 100.0])
        
    Returns:
        - A single float if one mode exists
        - A list of floats if multiple modes exist
        - None if input is empty
        
    Example:
        get_transaction_mode([10, 20, 20, 30]) → 20.0
        get_transaction_mode([5, 5, 10, 10]) → [5.0, 10.0]
    """
    if not amounts:
        return None

    # Count frequencies
    counter = Counter(amounts)
    max_freq = max(counter.values())
    
    # Get all values with max frequency
    modes = [float(val) for val, freq in counter.items() if freq == max_freq]
    
    # Return single value if unimodal, else list
    return modes[0] if len(modes) == 1 else sorted(modes)


# Example: Fraud detection in banking
if __name__ == "__main__":
    hourly_transactions = [49.99, 9.99, 49.99, 100.0, 49.99, 25.50]
    suspicious = [1.00, 1.00, 5.00, 5.00]
    empty_window = []

    print("Top transaction amount:", get_transaction_mode(hourly_transactions))
    print("Multiple common amounts:", get_transaction_mode(suspicious))
    print("No transactions:", get_transaction_mode(empty_window))
qa

Best Practices & Quick Wins

Conclusion

In banking, the mode isn’t just a statistic—it’s a signal. Whether it’s $0.99 test charges or repeated $500 transfers, the most frequent value often reveals intent. By using a robust, flexible mode function like get_transaction_mode, your fraud detection system gains:

When every transaction counts, the mode ensures you’re watching the right one.