Skip to main content

Rand Engine v2. Package with some methods to generate random data in different formats. Great to mock data while testing or developing.

Project description

Rand Engine

High-performance synthetic data generation for testing, development, and prototyping.

A Python library for generating millions of rows of realistic synthetic data through declarative specifications. Built on NumPy and Pandas for maximum performance.

Python Tests License


📦 Installation

pip install rand-engine

🎯 Who Is This For?

  • Data Engineers: Test ETL/ELT pipelines without production data dependencies
  • QA Engineers: Generate realistic datasets for load and integration testing
  • Data Scientists: Mock data during model development and validation
  • Backend Developers: Populate development and staging environments
  • BI Professionals: Create demos and POCs without exposing sensitive data

🚀 Quick Start

1. Use Pre-Built Examples (Fastest Way)

Get started immediately with ready-to-use specifications:

from rand_engine import DataGenerator, RandSpecs

# Generate 10,000 customer records
customers = DataGenerator(RandSpecs.customers(), seed=42).size(10000).get_df()
print(customers.head())

Output:

   customer_id       name  age                    email  is_active  account_balance
0    C00000001  John Smith   42    john.smith@email.com       True         15432.50
1    C00000002  Jane Brown   28   jane.brown@email.com       True          8721.33
2    C00000003   Bob Wilson   56   bob.wilson@email.com      False         42156.89
3    C00000004  Alice Davis   33  alice.davis@email.com       True         23400.12
4    C00000005   Tom Miller   49   tom.miller@email.com       True         31245.67

Available Pre-Built Specs:

from rand_engine import RandSpecs

# 🛒 E-commerce & Retail
RandSpecs.customers()    # Customer profiles (6 fields)
RandSpecs.products()     # Product catalog (6 fields)
RandSpecs.orders()       # Order records with currency/country (6 fields)
RandSpecs.invoices()     # Invoice records (6 fields)
RandSpecs.shipments()    # Shipping data with carrier/destination (6 fields)

# 💰 Financial
RandSpecs.transactions() # Financial transactions (6 fields)

# 👥 HR & People
RandSpecs.employees()    # Employee records with dept/level/role (6 fields)
RandSpecs.users()        # Application users (6 fields)

# 🔧 IoT & Systems
RandSpecs.devices()      # IoT device data with status/priority (6 fields)
RandSpecs.events()       # Event logs (6 fields)

Complete Example:

from rand_engine import DataGenerator, RandSpecs

# Generate products
products = DataGenerator(RandSpecs.products()).size(1000).get_df()

# Generate orders
orders = DataGenerator(RandSpecs.orders(), seed=123).size(50000).get_df()

# Generate employee data
employees = DataGenerator(RandSpecs.employees()).size(500).get_df()

# Export to files
DataGenerator(RandSpecs.customers()).write \
    .size(100000) \
    .format("parquet") \
    .option("compression", "snappy") \
    .save("customers.parquet")

2. Create Custom Specifications

Build your own specs for specific use cases:

from rand_engine import DataGenerator

# Simple specification
spec = {
    "user_id": {
        "method": "unique_ids",
        "kwargs": {"strategy": "zint", "length": 8}
    },
    "age": {
        "method": "integers",
        "kwargs": {"min": 18, "max": 65}
    },
    "salary": {
        "method": "floats",
        "kwargs": {"min": 30000.0, "max": 150000.0, "round": 2}
    }
}

df = DataGenerator(spec, seed=42).size(10000).get_df()

📚 Core Generation Methods

Method Description Example Use Case
unique_ids Unique identifiers User IDs, order numbers
integers Random integers Ages, quantities, counts
floats Random decimals Prices, weights, measurements
floats_normal Normal distribution Heights, temperatures, scores
booleans True/False with probability Active flags, feature toggles
distincts Random selection Categories, statuses, types
distincts_prop Weighted selection Product mix, user tiers
unix_timestamps Date/time values Created dates, event times

Simple Example:

spec = {
    "product_id": {"method": "unique_ids", "kwargs": {"strategy": "zint"}},
    "price": {"method": "floats", "kwargs": {"min": 9.99, "max": 999.99, "round": 2}},
    "category": {"method": "distincts", "kwargs": {"distincts": ["Electronics", "Clothing", "Food"]}},
    "in_stock": {"method": "booleans", "kwargs": {"true_prob": 0.85}}
}

products = DataGenerator(spec).size(5000).get_df()

🎨 Real-World Use Cases

Testing ETL Pipelines

from rand_engine import DataGenerator, RandSpecs

# Generate source data
source_df = DataGenerator(RandSpecs.transactions(), seed=42).size(1_000_000).get_df()

# Export to staging
source_df.to_parquet("staging/transactions.parquet")

# Run your ETL pipeline
# ...

# Generate more data for incremental loads
incremental_df = DataGenerator(RandSpecs.transactions()).size(10_000).get_df()

Load Testing APIs

import requests
from rand_engine import DataGenerator, RandSpecs

# Generate test users
stream = DataGenerator(RandSpecs.users()).stream_dict(min_throughput=10, max_throughput=50)

for user in stream:
    response = requests.post("https://api.example.com/users", json=user)
    print(f"Created user {user['user_id']}: {response.status_code}")

Populating Development Databases

from rand_engine import DataGenerator, RandSpecs
from rand_engine.integrations._duckdb_handler import DuckDBHandler

# Generate data
customers = DataGenerator(RandSpecs.customers()).size(10_000).get_df()
orders = DataGenerator(RandSpecs.orders()).size(50_000).get_df()

# Insert into database
db = DuckDBHandler("dev_database.duckdb")
db.create_table("customers", "customer_id VARCHAR(10) PRIMARY KEY")
db.insert_df("customers", customers, pk_cols=["customer_id"])
db.create_table("orders", "order_id VARCHAR(10) PRIMARY KEY")
db.insert_df("orders", orders, pk_cols=["order_id"])
db.close()

QA Testing with Edge Cases

from rand_engine import DataGenerator

# Mix of normal and edge cases
spec = {
    "value": {"method": "floats", "kwargs": {"min": -999999.99, "max": 999999.99, "round": 2}},
    "status": {"method": "distincts", "kwargs": {"distincts": ["active", "deleted", "suspended", "pending"]}},
    "edge_case": {"method": "booleans", "kwargs": {"true_prob": 0.05}}  # 5% edge cases
}

test_data = DataGenerator(spec, seed=789).size(1000).get_df()
edge_cases = test_data[test_data['edge_case'] == True]

🔥 Advanced Features

Correlated Columns

Generate related data (device → OS, product → status, etc.):

# Example: orders() spec includes correlated currency & country
orders = DataGenerator(RandSpecs.orders()).size(1000).get_df()

# Result: 
# order_id  amount  currency  country
#       001  100.50      USD       US
#       002   85.30      EUR       DE
#       003  120.75      GBP       UK

Weighted Distributions

# Example: products() uses weighted categories
products = DataGenerator(RandSpecs.products()).size(10000).get_df()

# Result distribution:
# Electronics: ~40%
# Clothing: ~30%  
# Food: ~20%
# Books: ~10%

Streaming Generation

from rand_engine import DataGenerator, RandSpecs

# Generate continuous data stream
stream = DataGenerator(RandSpecs.events()).stream_dict(
    min_throughput=5,   # Minimum records/second
    max_throughput=15   # Maximum records/second
)

for event in stream:
    # Each record includes automatic timestamp_created
    print(f"[{event['timestamp_created']}] Event: {event['event_type']}")
    # Send to Kafka, Kinesis, etc.

Multiple Export Formats

from rand_engine import DataGenerator, RandSpecs

spec = RandSpecs.transactions()

# CSV with compression
DataGenerator(spec).write.size(100000).format("csv").option("compression", "gzip").save("data.csv.gz")

# Parquet with Snappy
DataGenerator(spec).write.size(1000000).format("parquet").option("compression", "snappy").save("data.parquet")

# JSON
DataGenerator(spec).write.size(50000).format("json").save("data.json")

Reproducible Data

from rand_engine import DataGenerator, RandSpecs

# Same seed = identical data
df1 = DataGenerator(RandSpecs.customers(), seed=42).size(1000).get_df()
df2 = DataGenerator(RandSpecs.customers(), seed=42).size(1000).get_df()

assert df1.equals(df2)  # True - perfect reproducibility

🗂️ Export & Integration

File Formats

from rand_engine import DataGenerator, RandSpecs

generator = DataGenerator(RandSpecs.orders())

# CSV
generator.write.size(10000).format("csv").save("orders.csv")

# Parquet (recommended for large datasets)
generator.write.size(1000000).format("parquet").save("orders.parquet")

# JSON
generator.write.size(5000).format("json").save("orders.json")

# Multiple files (partitioned)
generator.write.size(1000000).num_files(10).format("parquet").save("orders/")

Database Integration

DuckDB:

from rand_engine import DataGenerator, RandSpecs
from rand_engine.integrations._duckdb_handler import DuckDBHandler

# Generate data
df = DataGenerator(RandSpecs.employees()).size(10000).get_df()

# Insert into DuckDB
db = DuckDBHandler("analytics.duckdb")
db.create_table("employees", "employee_id VARCHAR(10) PRIMARY KEY")
db.insert_df("employees", df, pk_cols=["employee_id"])

# Query
result = db.select_all("employees")
print(result.head())

db.close()

SQLite:

from rand_engine.integrations._sqlite_handler import SQLiteHandler

db = SQLiteHandler("test.db")
db.create_table("users", "user_id VARCHAR(10) PRIMARY KEY")
db.insert_df("users", df, pk_cols=["user_id"])
db.close()

📖 Exploring Available Specs

Want to see what's inside each pre-built spec?

from rand_engine import RandSpecs
import json

# View any spec structure
spec = RandSpecs.customers()
print(json.dumps(spec, indent=2))

# Output shows all fields and generation methods:
# {
#   "customer_id": {
#     "method": "unique_ids",
#     "kwargs": {"strategy": "zint", "prefix": "C"}
#   },
#   "name": {
#     "method": "distincts",
#     "kwargs": {"distincts": ["John Smith", "Jane Brown", ...]}
#   },
#   ...
# }

Try different specs:

# See all available specs
print(RandSpecs.products())
print(RandSpecs.transactions())
print(RandSpecs.devices())
print(RandSpecs.events())

Each spec demonstrates different generation techniques - use them as templates for your own custom specs!


🛠️ Creating Custom Specs

Basic Template

from rand_engine import DataGenerator

my_spec = {
    "id": {
        "method": "unique_ids",
        "kwargs": {"strategy": "zint"}
    },
    "name": {
        "method": "distincts",
        "kwargs": {"distincts": ["Alice", "Bob", "Charlie"]}
    },
    "value": {
        "method": "floats",
        "kwargs": {"min": 0.0, "max": 100.0, "round": 2}
    }
}

df = DataGenerator(my_spec).size(1000).get_df()

Spec Validation

Enable validation to catch errors early:

invalid_spec = {
    "age": {
        "method": "integers"  # Missing required "min" and "max"
    }
}

try:
    generator = DataGenerator(invalid_spec, validate=True)
except Exception as e:
    print(e)
    # ❌ Column 'age': Missing required parameter 'min'
    #    Correct example:
    #    {
    #        "age": {
    #            "method": "integers",
    #            "kwargs": {"min": 18, "max": 65}
    #        }
    #    }

🏗️ Architecture

Design Philosophy

  • Declarative: Specify what you want, not how to generate it
  • Performance: Built on NumPy for vectorized operations (millions of rows/second)
  • Simplicity: Pre-built examples for immediate use
  • Extensibility: Easy to create custom specifications

Public API

from rand_engine import DataGenerator, RandSpecs

# That's it! Simple and clean.

All internal modules (prefixed with _) are implementation details.


🧪 Quality & Testing

  • 212 tests passing
  • Comprehensive coverage of all generation methods
  • Validated on millions of generated records
  • Battle-tested in production ETL pipelines
# Run tests
pytest

# With coverage report
pytest --cov=rand_engine --cov-report=html

💡 Tips & Best Practices

For Data Engineers

  • Use seed parameter for reproducible test data
  • Export to Parquet with compression for large datasets
  • Use streaming mode for continuous data generation
  • Leverage pre-built specs to quickly scaffold test environments

For QA Engineers

  • Start with pre-built specs (RandSpecs)
  • Use validation mode (validate=True) during development
  • Generate edge cases with low probability booleans
  • Create multiple test datasets with different seeds

Performance Tips

  • Generate data in batches for optimal memory usage
  • Use Parquet format for large datasets (10x smaller than CSV)
  • Enable compression for file exports
  • Reuse DataGenerator instances when generating multiple datasets

📄 Requirements

  • Python: >= 3.10
  • numpy: >= 2.1.1
  • pandas: >= 2.2.2
  • faker: >= 28.4.1 (optional)
  • duckdb: >= 1.1.0 (optional)

🤝 Contributing

Contributions are welcome! See our Contributing Guide for details.


📞 Support


📄 License

MIT License - see LICENSE file for details.


🌟 Star History

If you find this project useful, consider giving it a ⭐ on GitHub!


Built with ❤️ for Data Engineers, QA Engineers, and the entire data community

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

rand_engine-0.6.0.tar.gz (32.8 kB view details)

Uploaded Source

Built Distribution

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

rand_engine-0.6.0-py3-none-any.whl (38.8 kB view details)

Uploaded Python 3

File details

Details for the file rand_engine-0.6.0.tar.gz.

File metadata

  • Download URL: rand_engine-0.6.0.tar.gz
  • Upload date:
  • Size: 32.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for rand_engine-0.6.0.tar.gz
Algorithm Hash digest
SHA256 566eb0dee8b452e4434fb3591d03a83eaab445e804edf8efb6d9e7e89d0c9ede
MD5 c8ec81b7566f5c37bb18e1897c5472d4
BLAKE2b-256 488bf1cc3df106ca8357e93aa663c7fe97e23084eaea91c9a1bdd03eb7905a19

See more details on using hashes here.

Provenance

The following attestation bundles were made for rand_engine-0.6.0.tar.gz:

Publisher: auto_tag_publish_master.yml on marcoaureliomenezes/rand_engine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rand_engine-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: rand_engine-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 38.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for rand_engine-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 29e4a73c4c33f504bc61b27a3bb9182cacbfbf3198c4de51c394254acb258b74
MD5 34efce8b3a370c8202784c8f7cb78361
BLAKE2b-256 49aee414d60a22f1fd8b3801f582c980df46c131a3a87ea8fcd2ff0cd95e2f17

See more details on using hashes here.

Provenance

The following attestation bundles were made for rand_engine-0.6.0-py3-none-any.whl:

Publisher: auto_tag_publish_master.yml on marcoaureliomenezes/rand_engine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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