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)

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)

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

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.