Skip to main content

Tiny, extensible pandas utilities for aliasing and basic data cleaning

Project description

Cleanroom 🧹

Tiny, extensible pandas utilities for aliasing and basic data cleaning

Cleanroom provides a simple set of pure functions you can compose to clean messy real-world data. It's designed to be lightweight, extensible, and work seamlessly with pandas DataFrames.

🚀 Features

  • Flexible Column Matching: Automatically detects column variations (first_name, First Name, f name, fname, etc.)
  • Email Cleaning: Normalize email addresses to lowercase
  • Name Formatting: Smart title case with proper handling of particles (van, de, etc.)
  • Phone Standardization: Convert phone numbers to international format
  • Address Normalization: Clean ZIP codes, standardize states and countries
  • Schema-Based Cleaning: Apply custom cleaning rules with flexible schemas
  • Auto-Clean: Automatically clean common columns with zero configuration

📦 Installation

pip install cleanroom

🔧 Quick Start

import pandas as pd
import cleanroom

# Sample messy data
df = pd.DataFrame({
    'f name': ['  john ', 'JANE'],
    'e-mail': ['JOHN@EXAMPLE.COM', 'jane@TEST.org'],
    'pnumber': ['(555) 123-4567', '555.987.6543'],
    'zip code': ['12345-6789', '98765'],
    'st': ['California', 'TX']
})

# One-line cleaning with flexible column matching
cleaned_df = cleanroom.auto_clean(df)
print(cleaned_df)

Output:

  f name e-mail              pnumber    zip code st
0   John  john@example.com   +15551234567  123456789  CA
1   Jane  jane@test.org      +15559876543     98765  TX

📚 API Reference

Individual Cleaning Functions

clean_email(series)

Normalize email addresses to lowercase and strip whitespace.

emails = pd.Series(['  JOHN@EXAMPLE.COM  ', 'jane@TEST.org'])
cleaned = cleanroom.clean_email(emails)
# Result: ['john@example.com', 'jane@test.org']

clean_name(series, alias_map=None, case="title")

Clean and format names with smart title casing.

names = pd.Series(['  john smith  ', 'JANE DOE', 'bob o\'connor'])
cleaned = cleanroom.clean_name(names)
# Result: ['John Smith', 'Jane Doe', 'Bob O\'Connor']

# With custom aliases
aliases = {'johnny': 'John', 'bobby': 'Robert'}
cleaned = cleanroom.clean_name(names, alias_map=aliases)

clean_phone(series, default_country="US")

Standardize phone numbers to international format.

phones = pd.Series(['(555) 123-4567', '555.987.6543', '+1-800-555-0199'])
cleaned = cleanroom.clean_phone(phones)
# Result: ['+15551234567', '+15559876543', '+18005550199']

clean_number(series)

Extract only digits (useful for ZIP codes, IDs).

zips = pd.Series(['12345-6789', 'ABC 98765', '  54321  '])
cleaned = cleanroom.clean_number(zips)
# Result: ['123456789', '98765', '54321']

clean_state(series, state_map=None)

Standardize US state names to abbreviations.

states = pd.Series(['California', 'TX', 'new york'])
cleaned = cleanroom.clean_state(states)
# Result: ['CA', 'TX', 'NY']

clean_country(series, country_map=None)

Standardize country names to ISO codes.

countries = pd.Series(['United States', 'USA', 'United Kingdom'])
cleaned = cleanroom.clean_country(countries)
# Result: ['US', 'US', 'GB']

DataFrame Operations

auto_clean(df)

Automatically clean common columns with flexible name matching.

Recognizes these column patterns:

  • Email: email, e-mail, mail, email_address, e_mail
  • Names: first_name, First Name, fname, f_name, given_name
  • Phone: phone, telephone, pnumber, phone_number, mobile
  • Address: zip, zip_code, postal_code, state, country
# Works with any column naming convention
df_messy = pd.DataFrame({
    'First Name': ['john', 'JANE'],
    'family name': ['smith', 'DOE'],  
    'E-Mail Address': ['JOHN@EXAMPLE.COM', 'jane@test.org'],
    'telephone': ['(555) 123-4567', '555.987.6543']
})

cleaned = cleanroom.auto_clean(df_messy)

apply_schema(df, schema)

Apply custom cleaning rules with a flexible schema.

schema = {
    'clean_email': {
        'func': cleanroom.clean_email,
        'source': ['email', 'email_address', 'e_mail']  # Try multiple columns
    },
    'full_name': {
        'func': cleanroom.clean_name,
        'source': ['first_name', 'last_name'],  # Combine columns
        'kwargs': {'case': 'title'}
    }
}

cleaned_df = cleanroom.apply_schema(df, schema)

🌍 Flexible Column Matching

Cleanroom automatically handles various column naming conventions:

Data Type Recognized Patterns
First Name first_name, First Name, fname, f_name, f name, firstname, given_name
Last Name last_name, Last Name, lname, surname, family_name, lastname
Email email, e-mail, mail, email_address, e_mail
Phone phone, telephone, pnumber, phone_number, mobile, cell
ZIP Code zip, zip_code, zipcode, postal_code, postcode
State state, st, province, region
Country country, nation, nationality

🏗️ Design Philosophy

  • Simple: Small set of pure functions you can compose
  • Extensible: Pass custom alias maps and cleaning rules
  • Flexible I/O: Works on pd.Series, DataFrame columns, or entire DataFrames
  • Non-destructive: Always returns new objects, never modifies input data
  • Pandas-native: Leverages pandas' powerful string operations

🧪 Examples

Real-world messy data

import pandas as pd
import cleanroom

# Typical messy customer data
customers = pd.DataFrame({
    'f name': ['  alice  ', 'BOB', 'Charlie Brown'],
    'surname': ['SMITH', 'jones', 'o\'connor'],
    'e-mail': ['ALICE@GMAIL.COM', 'bob@YAHOO.com', '  charlie@test.org  '],
    'pnumber': ['555-1234', '(800) 555-0199', '+1.212.555.9876'],
    'zip code': ['12345-6789', 'ABC 90210', '10001'],
    'st': ['California', 'TX', 'new york'],
    'nation': ['USA', 'United States', 'US']
})

# Clean everything with one function call
clean_customers = cleanroom.auto_clean(customers)

Custom cleaning pipeline

# Build your own cleaning pipeline
def clean_customer_data(df):
    result = df.copy()
    
    # Clean emails
    if 'email' in result.columns:
        result['email'] = cleanroom.clean_email(result['email'])
    
    # Standardize names with custom aliases
    name_aliases = {'bobby': 'Robert', 'mike': 'Michael'}
    if 'first_name' in result.columns:
        result['first_name'] = cleanroom.clean_name(
            result['first_name'], 
            alias_map=name_aliases
        )
    
    return result

📋 Requirements

  • Python 3.8+
  • pandas >= 1.3.0
  • numpy >= 1.21.0

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

MIT License - see LICENSE file for details.

🔗 Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pandas_cleanroom-1.0.0.tar.gz (9.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pandas_cleanroom-1.0.0-py3-none-any.whl (8.3 kB view details)

Uploaded Python 3

File details

Details for the file pandas_cleanroom-1.0.0.tar.gz.

File metadata

  • Download URL: pandas_cleanroom-1.0.0.tar.gz
  • Upload date:
  • Size: 9.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.6

File hashes

Hashes for pandas_cleanroom-1.0.0.tar.gz
Algorithm Hash digest
SHA256 a11b12dc7ffcb47ec3293e586a52bcd940f9fdae3774e78cdc0b9ce619977d9e
MD5 f586546fc41aa8e8b00858c49b512c4e
BLAKE2b-256 18844e035aa41507250c78ba50914836fa9ce588ab958fd4e09dc095ea4868ac

See more details on using hashes here.

File details

Details for the file pandas_cleanroom-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pandas_cleanroom-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 25186f1428b91eb778a53d881e67344836e2a4d54d226ab6110dd4f6f5c024d5
MD5 cabb98e4f92de4ae3f487a9fb33e8f44
BLAKE2b-256 b8196603f586a84aa7cc76dd71cda1ba677c4e9d4188b18154c34002e2702f98

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page