Loading...

Cleaning Unstructured Bank CSV Exports with Local Regex and Lightweight LLMs

Transaction exports from banks rarely display recognizable store names. Descriptions often include point-of-sale terminal IDs, processor codes, store numbers, and internal routing tags. Importing these strings into a spreadsheet creates duplicate merchant records and messy categories.

Image Description

You can clean bank CSV transactions using a two-stage process: filter out repetitive artifacts with regular expressions first, then let an offline language model categorize the cleaned merchant names without sharing data externally.

The Two-Tier Architecture: Deterministic First, AI Second

Using a language model to process thousands of raw CSV lines is slow and prone to formatting inconsistencies. A combined workflow works better:

  • Tier 1: Regular Expressions (Regex): Quickly removes predictable noise, including merchant codes, phone numbers, and payment gateway prefixes (like "SQ ", "TST", or "PAYPAL *").
  • Tier 2: Lightweight Local LLM: Evaluates the cleaned business names and assigns them to standard budget buckets, such as groceries, utilities, or dining.

Tier 1: Stripping Merchant Noise with Regex

Before categorizing names with an AI tool, run a simple regex script in Python or your spreadsheet editor to strip point-of-sale artifacts:

import re  def clean_merchant_string(raw_text):     # Remove common processor prefixes     text = re.sub(r'^(SQ	en|TST	en|PAYPAL	en|	en)', '', raw_text)     # Remove store numbers and sequential digits     text = re.sub(r'#	en+|	en{3,}', '', text)     # Remove trailing city/state references (e.g., NY 10001)     text = re.sub(r'[A-Z]{2}	en+', '', text)     # Collapse multiple spaces     return text.strip()

This step reduces strings like SQ *HARBOR COFFEE ROAST #4928 NEW YORK NY down to HARBOR COFFEE ROAST.

Tier 2: The Categorization Prompt for Local Models

After cleaning the raw text, send the unique merchant names to a local model (such as Llama 3 8B or Mistral 7B) using this structured JSON prompt:

You are a financial classification assistant. Normalize each merchant and map it to a standard budget category. Output ONLY valid JSON array with no conversational commentary.  Allowed Categories: Dining, Groceries, Utilities, Transport, Subscriptions, Retail.  Input List: ["HARBOR COFFEE ROAST", "AMZN MKTPLACE", "SHELL OIL"]  Output Format: [   {"raw": "HARBOR COFFEE ROAST", "clean": "Harbor Coffee", "category": "Dining"} ]

Because the output is restricted to JSON, the resulting table can be imported straight into your budgeting spreadsheet without manual cleanup or cloud exposure.

FAQ

Can I run this workflow entirely inside Microsoft Excel or Google Sheets?

Yes. You can use spreadsheet regex functions like REGEXREPLACE to strip prefixes and store codes, then export the cleaned merchant list for classification.

Why not let the LLM do the regex stripping work as well?

Regex handles pattern matching in microseconds with complete predictability. Using an LLM for simple text replacement uses unnecessary compute and risks unexpected text changes.

Is my financial privacy protected with this workflow?

Yes. Running both the script and the language model on your own device ensures that account numbers, dates, and spending records remain offline.

Key Takeaways

  • Bank CSV files contain point-of-sale prefixes, store codes, and system tags.
  • A two-tier setup uses regex for text cleanup and an LLM for categorization.
  • Regex strips predictable processor codes quickly and reliably.
  • Limiting model outputs to JSON makes spreadsheet imports straightforward.
  • Local processing keeps your transaction history off third-party servers.

Related Reading

  • How Local Large Language Models Can Parse Bank Statements Privately
  • Prompt Engineering Guardrails for Financial Spreadsheets and LLM Parsers
  • On-Device Neural Engines: Running Local Spending Classifiers on Consumer Silicon

Tagsberulearning