Python implementation of RTHOR (Randomization test of hypothesized order relations)
Project description
rthor
rthor is a Python implementation of RTHOR (Randomization Test of Hypothesized Order Relations), a statistical test for circumplex and circular models in correlation matrices.
Features
- Exact Parity with RTHORR: Produces numerically identical results to the original RTHORR package
- Multiple Input Formats: Works with files, pandas DataFrames, or numpy arrays
- Flexible Analysis: Test single matrices or compare multiple matrices pairwise
- Fast Performance: Vectorized operations using NumPy for efficient computation
Quick Start
import rthor
# Test from correlation matrix file
df = rthor.test(
"correlations.txt",
order="circular6",
n_matrices=3,
n_variables=6,
labels=["Sample 1", "Sample 2", "Sample 3"]
)
# View results (returns a pandas DataFrame)
print(df)
| matrix | predictions | agreements | ties | ci | p_value | label | n_permutations | n_variables | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 72 | 59 | 1 | 0.652778 | 0.016667 | Sample 1 | 720 | 6 |
| 1 | 2 | 72 | 53 | 1 | 0.486111 | 0.033333 | Sample 2 | 720 | 6 |
| 2 | 3 | 72 | 56 | 3 | 0.597222 | 0.016667 | Sample 3 | 720 | 6 |
df[df['ci'] > 0.5] # Filter results
| matrix | predictions | agreements | ties | ci | p_value | label | n_permutations | n_variables | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 72 | 59 | 1 | 0.652778 | 0.016667 | Sample 1 | 720 | 6 |
| 2 | 3 | 72 | 56 | 3 | 0.597222 | 0.016667 | Sample 3 | 720 | 6 |
# Or print formatted results
rthor.print_results(df)
RTHOR Test Results 3 matrices • 6 variables • 72 predictions • 720 permutations ╭──────────────┬────┬───────┬────────────────┬──────────────┬─────────────┬─────────────╮ │ Matrix │ │ CI │ Interpretation │ Significance │ Satisfied │ Violated │ ├──────────────┼────┼───────┼────────────────┼──────────────┼─────────────┼─────────────┤ │ [1] Sample 1 │ ↗ │ 0.653 │ Good fit │ p<.05 * │ 59/72 (82%) │ 12/72 (17%) │ │ [2] Sample 2 │ → │ 0.486 │ Moderate fit │ p<.05 * │ 53/72 (74%) │ 18/72 (25%) │ │ [3] Sample 3 │ ↗ │ 0.597 │ Good fit │ p<.05 * │ 56/72 (78%) │ 13/72 (18%) │ ╰──────────────┴────┴───────┴────────────────┴──────────────┴─────────────┴─────────────╯ ℹ️ Higher CI values indicate better fit (range: -1 to +1)
Test from DataFrames
df = rthor.test(
[df1, df2, df3],
order="circular6",
labels=["Group A", "Group B", "Group C"],
print_results=True # Print formatted results automatically
)
RTHOR Test Results 3 matrices • 6 variables • 72 predictions • 720 permutations ╭─────────────┬────┬───────┬────────────────┬──────────────┬──────────────┬─────────────╮ │ Matrix │ │ CI │ Interpretation │ Significance │ Satisfied │ Violated │ ├─────────────┼────┼───────┼────────────────┼──────────────┼──────────────┼─────────────┤ │ [1] Group A │ ✓ │ 1.000 │ Excellent fit │ p<.05 * │ 72/72 (100%) │ 0/72 (0%) │ │ [2] Group B │ ↗ │ 0.583 │ Good fit │ p<.05 * │ 57/72 (79%) │ 15/72 (21%) │ │ [3] Group C │ ⚠ │ 0.056 │ Minimal fit │ p=0.433 │ 38/72 (53%) │ 34/72 (47%) │ ╰─────────────┴────┴───────┴────────────────┴──────────────┴──────────────┴─────────────╯ ℹ️ Higher CI values indicate better fit (range: -1 to +1)
Compare multiple matrices
individual, pairwise = rthor.compare(
[df1, df2, df3],
order="circular6",
print_results=True
)
RTHOR Matrix Comparison 3 matrices • 6 variables • 72 predictions • 720 permutations ╭────────────┬────┬────────┬─────────────────┬──────────────┬───────┬────────┬────────╮ │ Comparison │ │ CI │ Result │ Significance │ Both │ Only 1 │ Only 2 │ ├────────────┼────┼────────┼─────────────────┼──────────────┼───────┼────────┼────────┤ │ Matrix 1 │ ✓ │ 1.000 │ Excellent fit │ p<.05 * │ 72/72 │ — │ — │ │ Matrix 2 │ ↗ │ 0.583 │ Good fit │ p<.05 * │ 57/72 │ — │ — │ │ Matrix 3 │ ⚠ │ 0.056 │ Minimal fit │ p=0.433 │ 38/72 │ — │ — │ ├────────────┼────┼────────┼─────────────────┼──────────────┼───────┼────────┼────────┤ │ 1 vs 2 │ ↓ │ -0.208 │ Matrix 1 better │ p=0.933 │ 57 │ 15 │ 0 │ │ 1 vs 3 │ ↓ │ -0.472 │ Matrix 1 better │ p=0.983 │ 38 │ 34 │ 0 │ │ 2 vs 3 │ ↓ │ -0.264 │ Matrix 2 better │ p=0.967 │ 37 │ 20 │ 1 │ ╰────────────┴────┴────────┴─────────────────┴──────────────┴───────┴────────┴────────╯ Info: Positive CI means matrix 2 fits better, negative means matrix 1 fits better
Installation
See Installation Instructions for more details.
pip install rthor
What is RTHOR?
RTHOR (Randomization Test of Hypothesized Order Relations) is a statistical method for testing whether correlation matrices conform to a hypothesized ordering of variables [@Tracey2025RTHORR;@Tracey1997RANDALL]. This is particularly useful for:
- Circumplex Models: Variables arranged in a circular pattern (e.g., interpersonal behavior, emotions)
- Circular Structures: Testing theoretical predictions about variable ordering
- Correlation Patterns: Validating expected patterns in correlation matrices
The test uses a randomization approach to compute p-values, comparing the observed Correspondence Index (CI) with values from permuted data. CI ranges from -1 (perfect disagreement) to +1 (perfect agreement).
Key Functions
rthor.test()
Test whether correlation matrices conform to a hypothesized ordering.
Parameters:
data: Input data (file path, list of DataFrames, or numpy array)order: Hypothesized ordering ("circular6", "circular8", or custom list)labels: Optional descriptive labels for matricesn_matrices: Number of matrices (required for file input)n_variables: Number of variables (required for file input)print_results: If True, print formatted results table
Returns: pandas DataFrame with columns: matrix, predictions, agreements, ties, ci, p_value, label, n_permutations, n_variables
rthor.compare()
Compare multiple correlation matrices pairwise to determine which fits the hypothesis better.
Parameters: Same as rthor.test() but requires at least 2 matrices
Returns: Tuple of two pandas DataFrames: (individual_results, pairwise_comparisons)
Documentation
Full documentation is available at https://drandrewmitchell.com/rthor
Validation Against Original Paper
The implementation has been validated against the original Hubert & Arabie (1987) [@Hubert1987Evaluating] paper. See docs/examples/paper-validation.py for a detailed demonstration that replicates Table 1 from the paper and confirms exact agreement with the expected results:
- ✓ 72 predictions, 61 agreements, 11 violations
- ✓ p-value = 0.0167 (12/720)
- ✓ CI = 0.694
Testing
Run tests across all supported Python versions:
tox
Run tests in current environment:
pytest tests
Run tests with coverage:
pytest --cov --cov-report=xml
Development
This project uses:
- uv for dependency management
- ruff for linting and formatting
- pytest for testing
- mkdocs with Material theme for documentation
- pre-commit hooks (via prek) for code quality
Install development dependencies:
uv sync --all-extras
Run pre-commit hooks:
uv run prek run -a
Build documentation:
uv run mkdocs serve
Project Team
Andrew Mitchell (andrew.mitchell.research@gmail.com)
Research Software Engineering Contact
Centre for Advanced Research Computing, University College London (arc.collaborations@ucl.ac.uk)
Citation
If you use rthor in your research, please cite both this package and the original method paper:
rthor (Python implementation):
@software{Mitchell2025rthor,
author = {Mitchell, Andrew},
license = {MIT},
title = {{rthor: Python implementation of RTHOR (Randomization test of hypothesized order relations)}},
url = {https://github.com/MitchellAcoustics/rthor}
}
Original RTHOR method:
@article{Hubert1987Evaluating,
author = {Hubert, Lawrence and Arabie, Phipps},
year = {1987},
month = {07},
pages = {172-178},
title = {Evaluating Order Hypotheses Within Proximity Matrices},
volume = {102},
journal = {Psychological Bulletin},
doi = {10.1037/0033-2909.102.1.172}
}
R RTHORR package:
@software{Tracey2025RTHORR,
title = {RTHORR: randomization test of hypothesized order relations (RTHOR) and
comparisons},
author = {Terence J. G. Tracey and Michael L. Morris},
year = {2025},
note = {R package version 0.1.3, commit c3edb36287c77733ec0a23236b478cc53c1cac0f},
url = {https://github.com/michaellynnmorris/RTHORR}
}
License
MIT License. See LICENSE.md for details.
Acknowledgments
This project is developed in collaboration with the Centre for Advanced Research Computing, University College London.
rthor is a Python port of the R package RTHORR by Michael B. Gurtman. The implementation maintains exact numerical parity with the original R version while providing a Pythonic interface and improved performance through vectorization.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rthor-0.2.1.tar.gz.
File metadata
- Download URL: rthor-0.2.1.tar.gz
- Upload date:
- Size: 46.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8bcf87a036fd148574d45b5f6c953d1750a5d2cc8a66f0c8229f966a196e74f
|
|
| MD5 |
274332875653164b983e76768bff81da
|
|
| BLAKE2b-256 |
1ae7a9a70fb1519305cccd61cacbaac169a6493468b6707a7b8c60890df963f9
|
File details
Details for the file rthor-0.2.1-py3-none-any.whl.
File metadata
- Download URL: rthor-0.2.1-py3-none-any.whl
- Upload date:
- Size: 25.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a223e3c8050fe7c6e2a88a0367beccc65f1bd77dd9fe96895bf557348220b34
|
|
| MD5 |
4f34bfbf65cb0e3e79624a18b3fc09b7
|
|
| BLAKE2b-256 |
ce385f22a877b3f5eeb402cfc6633e6946881af126f2e477569b3abb43d4e399
|