Skip to main content

Lightning-fast dataframe comparison library built in Rust with Python bindings

Project description

RDataCompy

Lightning-fast dataframe comparison library, implemented in Rust with Python bindings.

Overview

RDataCompy is a high-performance library for comparing dataframes, inspired by Capital One's datacompy. Built in Rust and leveraging Apache Arrow, it provides 40+ million cells/second throughput with comprehensive comparison reports.

Why RDataCompy?

  • 🚀 Blazing Fast: 40-46M cells/second (100-1000x faster than Python-based solutions)
  • Memory Efficient: Zero-copy operations using Apache Arrow columnar format
  • 🎯 Flexible: Configurable tolerance for numeric comparisons
  • Comprehensive: Detailed reports showing exact differences
  • 🔧 Multi-Format: Works with PyArrow, Pandas, PySpark, and Polars DataFrames
  • Decimal Support: Full DECIMAL(p,s) support with cross-precision compatibility

Installation

pip install rdatacompy

Optional Dependencies

# For PySpark support
pip install rdatacompy[spark]

# For Pandas support
pip install rdatacompy[pandas]

# For Polars support
pip install rdatacompy[polars]

# Install everything
pip install rdatacompy[all]

Quick Start

Basic Usage (PyArrow)

import pyarrow as pa
from rdatacompy import Compare

# Create sample tables
df1 = pa.table({
    'id': [1, 2, 3, 4],
    'value': [10.0, 20.0, 30.0, 40.0],
    'name': ['Alice', 'Bob', 'Charlie', 'David']
})

df2 = pa.table({
    'id': [1, 2, 3, 5],
    'value': [10.001, 20.0, 30.5, 50.0],
    'name': ['Alice', 'Bob', 'Chuck', 'Eve']
})

# Compare dataframes
comp = Compare(
    df1, 
    df2,
    join_columns=['id'],
    abs_tol=0.01,  # Absolute tolerance for floats
    df1_name='original',
    df2_name='updated'
)

# Print comprehensive report
print(comp.report())

Using with Pandas

import pandas as pd
from rdatacompy import Compare

df1 = pd.DataFrame({
    'id': [1, 2, 3],
    'amount': [100.50, 200.75, 300.25]
})

df2 = pd.DataFrame({
    'id': [1, 2, 3],
    'amount': [100.51, 200.75, 300.24]
})

# Directly compare Pandas DataFrames (auto-converted to Arrow)
comp = Compare(df1, df2, join_columns=['id'], abs_tol=0.01)
print(comp.report())

Using with PySpark

from pyspark.sql import SparkSession
from rdatacompy import Compare

# For Spark 3.5, enable Arrow for better performance
spark = SparkSession.builder \
    .config("spark.sql.execution.arrow.pyspark.enabled", "true") \
    .getOrCreate()

df1 = spark.createDataFrame([(1, 100), (2, 200)], ['id', 'value'])
df2 = spark.createDataFrame([(1, 100), (2, 201)], ['id', 'value'])

# Directly compare Spark DataFrames (auto-converted to Arrow)
# Works with Spark 3.5+ (via toPandas) and 4.0+ (via toArrow)
comp = Compare(df1, df2, join_columns=['id'])
print(comp.report())

Decimal Support

from decimal import Decimal
import pyarrow as pa
from rdatacompy import Compare

# Compare DECIMAL columns with different precision/scale
df1 = pa.table({
    'id': [1, 2, 3],
    'price': pa.array([
        Decimal('123.456789012345'),
        Decimal('999.999999999999'),
        Decimal('42.123456789012')
    ], type=pa.decimal128(28, 12))  # High precision
})

df2 = pa.table({
    'id': [1, 2, 3],
    'price': pa.array([
        Decimal('123.456789'),
        Decimal('999.999998'),
        Decimal('42.123457')
    ], type=pa.decimal128(18, 6))  # Lower precision
})

# Compare with tolerance - handles different precision automatically
comp = Compare(df1, df2, join_columns=['id'], abs_tol=0.00001)
print(comp.report())

Features

Comparison Report

The report includes:

  • DataFrame Summary: Row and column counts
  • Column Summary: Common columns, unique to each dataframe
  • Row Summary: Matched rows, unique rows, duplicates
  • Column Comparison: Which columns have differences
  • Sample Differences: Example rows with unequal values
  • Statistics: Number of differences, max difference, null differences

API Methods

comp = Compare(df1, df2, join_columns=['id'])

# Get full comparison report
report = comp.report()

# Check if dataframes match
matches = comp.matches()  # Returns bool

# Get common columns
common_cols = comp.intersect_columns()

# Get columns unique to each dataframe
df1_only = comp.df1_unq_columns()
df2_only = comp.df2_unq_columns()

Supported Data Types

  • ✅ Integers: int8, int16, int32, int64, uint8, uint16, uint32, uint64
  • ✅ Floats: float32, float64
  • ✅ Decimals: decimal128, decimal256 (with cross-precision compatibility)
  • ✅ Strings: utf8, large_utf8
  • ✅ Booleans
  • ✅ Dates: date32, date64
  • ✅ Timestamps (with timezone support)

Cross-Type Compatibility

RDataCompy is designed for real-world data migration scenarios:

# Compare different numeric types (int vs float vs decimal)
df1 = pa.table({'id': [1], 'val': pa.array([100], type=pa.int64())})
df2 = pa.table({'id': [1], 'val': pa.array([100.0], type=pa.float64())})
comp = Compare(df1, df2, join_columns=['id'])
comp.matches()  # True - types are compatible!

# Compare different decimal precisions
df1 = pa.table({'val': pa.array([Decimal('123.45')], type=pa.decimal128(28, 12))})
df2 = pa.table({'val': pa.array([Decimal('123.45')], type=pa.decimal128(18, 6))})
# Compares successfully - precision difference handled automatically

Performance

Benchmarked on a dataset with 150,000 rows × 200 columns (58.8M data points):

  • Comparison time: 1.3 seconds
  • Throughput: 46 million cells/second
  • Memory overhead: 16 MB (only stores differences)

vs datacompy

RDataCompy is significantly faster than Python-based solutions:

  • Columnar processing: Uses SIMD-optimized Arrow compute kernels
  • Zero-copy: Works directly on Arrow arrays without data duplication
  • Hash-based joins: O(n) row matching vs O(n²) pandas merge
  • No type inference: Arrow types known upfront (no runtime checks per column)

Development

Prerequisites

  • Rust 1.70+
  • Python 3.8+
  • maturin

Building from Source

# Clone repository
git clone https://github.com/yourusername/rdatacompy
cd rdatacompy

# Create virtual environment
python -m venv .venv
source .venv/bin/activate

# Install maturin
pip install maturin

# Build and install in development mode
maturin develop --release

# Run examples
python examples/basic_usage.py

Running Tests

# Rust tests
cargo test

# Python examples
python examples/test_multi_dataframe_types.py
python examples/test_decimal_types.py
python examples/benchmark_large.py

Contributing

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

License

Apache-2.0

Acknowledgments

Roadmap

See TODO.md for planned features and improvements.

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

rdatacompy-0.1.8-cp312-cp312-win_amd64.whl (782.5 kB view details)

Uploaded CPython 3.12Windows x86-64

rdatacompy-0.1.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (911.1 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

rdatacompy-0.1.8-cp311-cp311-win_amd64.whl (781.6 kB view details)

Uploaded CPython 3.11Windows x86-64

rdatacompy-0.1.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (910.1 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

rdatacompy-0.1.8-cp310-cp310-win_amd64.whl (781.7 kB view details)

Uploaded CPython 3.10Windows x86-64

rdatacompy-0.1.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (910.3 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

rdatacompy-0.1.8-cp39-cp39-win_amd64.whl (781.9 kB view details)

Uploaded CPython 3.9Windows x86-64

rdatacompy-0.1.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (910.8 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

rdatacompy-0.1.8-cp38-cp38-win_amd64.whl (781.9 kB view details)

Uploaded CPython 3.8Windows x86-64

rdatacompy-0.1.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (911.0 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ x86-64

File details

Details for the file rdatacompy-0.1.8-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for rdatacompy-0.1.8-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 0dcd5e885349060df679169c563368095a6983e5d2a2a2cbf9687ecb0f0cba39
MD5 368b142271830bd7a41914b33b39f64f
BLAKE2b-256 6eaa1535223f248b44366c84676a8756c6723ce4198f1cfdfe2375998e1784f1

See more details on using hashes here.

File details

Details for the file rdatacompy-0.1.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rdatacompy-0.1.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d6a72031d6c3846e8d60627bde528829a13b3d1eaa7d875537477fdee7964f63
MD5 be2c533be3e4fd6c5adf8b1522e307fb
BLAKE2b-256 8c3bacd64df808c66c8a3766428ac34e5af72f75af617ac99d9eec60f8ad63fc

See more details on using hashes here.

File details

Details for the file rdatacompy-0.1.8-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for rdatacompy-0.1.8-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 17904194e02991cb6ee4f639054ed7bbd0fc520e729f097e571b0ce56bb0ec54
MD5 86ea0abd3f840d9b21e976bd0b6b6855
BLAKE2b-256 c244cbe55bf7e8aa2d0ba37f3879bb47dcc8c85597baac1303e3360c30620884

See more details on using hashes here.

File details

Details for the file rdatacompy-0.1.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rdatacompy-0.1.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ea0f5acd66ad94ae2cdbd7aa9a9990e85ab07002b70099afa0dbbbeecf6f3918
MD5 a517b7012e07a53760bd7076813b2f95
BLAKE2b-256 1a469a9b61affb2b64f1de9c6fa2239b15d1842ebfa95e2dc81c2917139bdc1d

See more details on using hashes here.

File details

Details for the file rdatacompy-0.1.8-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for rdatacompy-0.1.8-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 6557d11189f374497c19ccf14ebbd5f7ff52e3f7cf6bd6e34cad40940c660bd5
MD5 dafb9b0cb69720ee8b20f82f29181e67
BLAKE2b-256 fb3507891328be83701b62c8dd81f9985e0a2702b8bf255eefde4077572d5f2f

See more details on using hashes here.

File details

Details for the file rdatacompy-0.1.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rdatacompy-0.1.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 71d3b8fc43a8644b9c6c391baa226e65a876412fbe7768bda3c4321a4f382935
MD5 afc1a4d6c9aebe680fcba710d4fc88f0
BLAKE2b-256 adc76489613b0c4459b69f388daff3890bd21f5d256876a0a041e742f970d8bc

See more details on using hashes here.

File details

Details for the file rdatacompy-0.1.8-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for rdatacompy-0.1.8-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 d5d81094c1bf0a842d20e46b59cc9625f86b52144e287ea6c3124feb2af5223b
MD5 1e1545eb46e9cd962db7740812da20f1
BLAKE2b-256 bc84fb356ea769672faa524ea1efdf3b69cb2b6e0639b03c4be301a8b008cd8c

See more details on using hashes here.

File details

Details for the file rdatacompy-0.1.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rdatacompy-0.1.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fb3ff8426e1255ba7ffcdaac2478c65d37772e0f9afce09b694354d7aff3fbdc
MD5 dd3fca645866d43eedf05ddf8f9b9f81
BLAKE2b-256 fa0aae0a250de046636e6edc245622da91aa82ee9981cebf81944ffa3a0458ac

See more details on using hashes here.

File details

Details for the file rdatacompy-0.1.8-cp38-cp38-win_amd64.whl.

File metadata

File hashes

Hashes for rdatacompy-0.1.8-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 1156fd0f9fbd8d6fbd7dc1f3faf61cf809492b02ea4e464fe855c71fc2362fe9
MD5 c48b74f0587a410017a7ab2c835bb9f6
BLAKE2b-256 4719d19f72ed29b4249007e3b807ca7d0ae68548b0c8ef8c0fa4a8acb6a531dd

See more details on using hashes here.

File details

Details for the file rdatacompy-0.1.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rdatacompy-0.1.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b1c7a384ce9c0852772174782915628e6549de2f68f9889fe20f2e2adb996b5f
MD5 cf6b8390d41e531d4a726e30b5088039
BLAKE2b-256 3fb8885af928c7c7e8b9c39b610d3908d3844e9ebe9accce7a3c15f5598db5e9

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