Mathew K Analytics

Lesson 2 · Python for Banking and Finance

Numbers, Strings, and Money in Banking

In this lesson, we will learn how to use Python to work with numbers and strings to analyze money data from real banking transactions. This problem matters…

⬇ Download notebookOpen in Colab ↗

What you'll learn

Data

No separate download needed — the notebook creates or downloads everything it uses.

📓 Full notebook

Download .ipynb

Numbers, Strings, and Money in Banking#

  • In this lesson, we will learn how to use Python to work with numbers and strings to analyze money data from real banking transactions.
  • This problem matters because banks handle huge amounts of numeric data, transaction descriptions, and strings every day.
  • By the end, you will understand how to process, clean, and analyze numbers and amounts, work with money safely, and avoid common errors.
  • You will build skills to extract value from messy text, convert values correctly, handle rounding, and automate checks for financial data.
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')

Core data concepts: banking transactions and money#

  • Banking transactions contain numbers (amounts), strings (reference info), and dates.
  • Amounts must be handled carefully to avoid losing cents due to rounding.
  • Transaction descriptions are messy strings and may contain errors or noise.
  • Beginners often forget to use the right data types for amounts and dates.
  • We must always work with the right formats to keep money calculations safe and precise.
np.random.seed(42)
n_transactions = 1000
n_customers = 200
df = pd.DataFrame({
    'transaction_id': range(1, n_transactions + 1),
    'customer_id': np.random.choice([f'CUST_{i:04d}' for i in range(1, n_customers + 1)], n_transactions),
    'amount': np.round(np.random.normal(150, 60, n_transactions), 2),
    'transaction_type': np.random.choice(['Debit', 'Credit'], n_transactions),
    'channel': np.random.choice(['ATM', 'Online', 'Branch', 'POS'], n_transactions),
    'date': pd.date_range(start='2024-01-01', periods=n_transactions, freq='h')
})
 
print(df.shape)
print(df.head(3))
(1000, 6)
   transaction_id customer_id  amount transaction_type channel  \
0               1   CUST_0103  238.77           Credit     ATM   
1               2   CUST_0180  269.17           Credit     POS   
2               3   CUST_0093   58.62           Credit  Online   

                 date  
0 2024-01-01 00:00:00  
1 2024-01-01 01:00:00  
2 2024-01-01 02:00:00  
print('Amount column types:', df['amount'].dtype)
print('First 5 amounts:', df['amount'].head().values)
Amount column types: float64
First 5 amounts: [238.77 269.17  58.62  81.85 163.56]
print('Transaction type unique values:', df['transaction_type'].unique())
print('Channel unique values:', df['channel'].unique())
Transaction type unique values: ['Credit' 'Debit']
Channel unique values: ['ATM' 'POS' 'Online' 'Branch']
# Convert numeric amounts to formatted strings with two decimal places
df['amount_str'] = df['amount'].apply(lambda x: f'${x:,.2f}')
print(df[['amount', 'amount_str']].head(3))
   amount amount_str
0  238.77    $238.77
1  269.17    $269.17
2   58.62     $58.62
# Convert string amounts back to float
amount_float = df['amount_str'].apply(lambda s: float(s.replace('$','').replace(',','')))
print('First 3 reconverted amounts:', amount_float.head(3).values)
First 3 reconverted amounts: [238.77 269.17  58.62]
# Example: simple sum of all transaction amounts
total_sum = df['amount'].sum()
print(f'Total value of all transactions: ${total_sum:,.2f}')
Total value of all transactions: $151,702.08
# Example: count number of credit vs debit transactions
count_types = df['transaction_type'].value_counts()
print(count_types)
transaction_type
Credit    503
Debit     497
Name: count, dtype: int64
# Intermediate: Find and correct negative transaction amounts (not allowed)
negatives = df[df['amount'] < 0]
if not negatives.empty:
    print(f'Found {len(negatives)} negative amounts. Setting to zero.')
    df.loc[df['amount'] < 0, 'amount'] = 0
else:
    print('No negative amounts found.')
Found 7 negative amounts. Setting to zero.
# Intermediate: extract numbers from messy text descriptions
examples = ['Paid $512.23 by EFT', 'ATM withdrawal $100', 'Salary $3000 for Feb', 'Refund of $54.9']
import re
amounts = [float(re.search(r'\$([0-9,.]+)', s).group(1).replace(',','')) for s in examples]
print('Extracted amounts:', amounts)
Extracted amounts: [512.23, 100.0, 3000.0, 54.9]
# Intermediate: Round all amounts to nearest dollar (bank rounding)
df['amount_rounded'] = df['amount'].round(0)
print(df[['amount', 'amount_rounded']].head())
   amount  amount_rounded
0  238.77           239.0
1  269.17           269.0
2   58.62            59.0
3   81.85            82.0
4  163.56           164.0
# Intermediate: create summary string for reporting
row = df.iloc[0]
summary = f"{row['date'].strftime('%Y-%m-%d')} | {row['transaction_type']} | {row['channel']} | {row['amount_str']}"
print('Example summary:', summary)
Example summary: 2024-01-01 | Credit | ATM | $238.77
# Advanced: Calculate rolling balance for a single customer by transaction date
single_customer = df[df['customer_id'] == df['customer_id'].iloc[0]].sort_values('date')
balance = single_customer['amount'].cumsum()
print('First 5 balances:', balance.head().values)
First 5 balances: [238.77 418.56 528.21 576.61 782.84]
# Advanced: Flag suspicious large transactions
high_threshold = 500
df['flagged'] = df['amount'] > high_threshold
print(df[['amount', 'flagged']].head())
   amount  flagged
0  238.77    False
1  269.17    False
2   58.62    False
3   81.85    False
4  163.56    False
# Advanced: Parse and split strings into structured columns
messy = pd.Series(['2024/01/01:ATM:$100', '2024/02/05:Online:$250', '2024/03/15:POS:$64.00'])
split_data = messy.str.split(':', expand=True)
split_data.columns = ['date', 'channel', 'amount_str']
split_data['amount'] = split_data['amount_str'].apply(lambda x: float(x.replace('$','')))
print(split_data)
         date channel amount_str  amount
0  2024/01/01     ATM       $100   100.0
1  2024/02/05  Online       $250   250.0
2  2024/03/15     POS     $64.00    64.0
# Error handling: Try converting an invalid string to float
try:
    bad_value = float('one hundred dollars')
except ValueError as e:
    print('Error:', e)
Error: could not convert string to float: 'one hundred dollars'
# Error handling: Removing currency words and extra spaces before float conversion
sample = ' USD  150.75 '
try:
    cleaned = sample.replace('USD','').strip()
    value = float(cleaned)
    print(value)
except ValueError:
    print('Cannot convert to float')
150.75

Best practices and lessons learned#

  • Always use float or Decimal types for money, never plain strings.
  • Convert and format amounts early, check for negative and huge values.
  • Clean and validate input before doing math; expect inconsistent formats.
  • Strings can hide valuable info. Use regular expressions wisely.
  • Use try-except for all type conversions involving user data.
# End-to-end: From raw strings to account summary
raw = ['2024-04-01:ATM:USD 100.50', '2024-04-02:Online:USD 200.00', '2024-04-05:POS:USD 50.75']
parts = [r.split(':') for r in raw]
df_e2e = pd.DataFrame(parts, columns=['date','channel','amount_str'])
df_e2e['amount'] = df_e2e['amount_str'].str.replace('USD','').astype(float)
balance = df_e2e['amount'].sum()
print('Account balance from all transactions:', balance)
Account balance from all transactions: 351.25

Recap: You mastered numbers, strings, and safe money processing!#

  • You learned to convert, clean, parse, and format amounts.
  • You learned how Python can avoid expensive banking mistakes.
  • Keep exploring: try new string patterns and error tests.
  • Watch more practical banking tutorials on YouTube!

Found this useful?

All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.