Skip to content

irelink

0.0.1Package record

Fast Probabilistic Record Linkage

0packages depend
169downloads / year
80.0%test coverage
13/13flavors OK

Overview

About

Performs fast, scalable probabilistic record linkage and deduplication using the Fellegi-Sunter model. Records lacking a shared unique identifier are compared across configurable dimensions using exact, fuzzy, and distance-based comparisons, with model parameters estimated via unsupervised Expectation-Maximization. Multiple SQL backends are supported through 'DBI', including execution via 'DuckDB'. This package is a translation of the Python 'splink' library by Linacre et al. (2022) doi:10.23889/ijpds.v7i3.1794 into idiomatic R.

Changes in 0.0.1

Initial development release, translating Python's splink probabilistic record linkage engine into idiomatic R.

Core pipeline

  • il_spec(), il_compare(), and il_block_on() define the linkage model declaratively: which fields to compare, how to compare them, and which blocking rules to apply.
  • il_model() binds a spec to one or two datasets and a DBI connection for dedupe, link, or link_and_dedupe, and accepts in-memory data frames, dbplyr::tbl_lazy references, or existing table-name strings.
  • predict() scores all candidate pairs above a match-probability threshold (or an evidence-only match-weight threshold via threshold_match_weight).
  • il_cluster() resolves scored pairs into entity clusters via connected components (using igraph) or single-best-link (with source_dataset for cross-source filtering).

Comparison library

  • String similarity: cl_exact(), cl_levenshtein(), cl_damerau_levenshtein(), cl_jaro(), cl_jaro_winkler(), cl_jaccard(), cl_cosine().
  • Numeric and distance: cl_numeric_diff(), cl_pct_diff(), cl_geo_distance().
  • Temporal: cl_date_diff() for date proximity with days(), months(), and years() helpers, and cl_time_diff() for sub-day precision with seconds(), minutes(), and hours() helpers.
  • Collections: cl_array_intersect(), cl_array_subset(), cl_array_min_distance().
  • Domain-specific: cl_name(), cl_first_last_name() / cl_forename_surname() (both accept a companion column for the surname and handle first/last swap detection), cl_dob(), cl_email(), cl_domain(), cl_soundex(), cl_zip_code() (exact, 5-digit ZIP+4, and 3-digit Sectional Center Facility prefix levels), cl_postcode().
Show all changes in 0.0.1Hide the rest of the changes in 0.0.1
  • Composition: cl_levels(), cl_and(), cl_or(), cl_not(), cl_null(), cl_else(), cl_literal(), cl_custom(), cl_columns_reversed().
  • All applicable comparators accept term_frequency = TRUE for Fellegi-Sunter term-frequency adjustments.

Column transforms

  • il_transform() composes multiple R functions into a chainable transform with SQL-side nesting (e.g. TRIM(LOWER(col))).
  • Column transform factories for SQL-side column expressions: il_substr(), il_regex_extract(), il_nullif(), il_cast_to_string(), il_try_parse_date(), il_array_element().
  • Built-in transforms auto-translated to SQL: tolower, toupper, trimws.
  • Phonetic transforms: il_soundex(), il_metaphone(), il_dmetaphone() (usable as R functions and SQL macros).

Blocking

  • il_block_on() and block_on() for equality-based and custom SQL blocking rules, with per-column transform support via formula syntax (col ~ transform, e.g. first_name ~ il_substr(1, 3)) or a named-list .transform for programmatic construction.
  • .explode parameter for array-valued blocking columns (generates UNNEST subqueries for DuckDB).
  • il_count_pairs() counts candidate pairs, including cumulative totals and percent-of-cartesian summaries across rule combinations, and can estimate counts from a deterministic record sample on large data through record_sample_proportion.
  • il_suggest_blocking() ranks candidate blocking rules by pair-reduction, coverage, and balanced score.
  • il_find_blocking_below() finds blocking rule combinations below a pair count ceiling.
  • block_from_labels() measures per-column recall from labeled pairs.
  • il_largest_blocks() identifies the blocking keys that generate the most records and pairs, respecting blocking transforms.

Training

  • il_estimate_u() estimates non-match probabilities from all candidate pairs when there are at most max_pairs, and otherwise from a uniform random sample of records (reproducible with set.seed()), with optional chunked estimation over random chunks through chunk_size and early stopping through min_count_per_level.
  • il_estimate_em() runs the Fellegi-Sunter EM algorithm with configurable max_iterations, convergence, fix_u, fix_m, fix_prior, derive_prior, estimate_without_tf, and estimator_mode parameters. An optional max_pairs cap trains on a deterministic record sample sized to produce about that many blocked pairs.
  • estimator_mode = "dependency-aware" fits log-linear matched and unmatched comparison-pattern distributions over aggregated gamma counts, preserving missing comparison states as explicit pattern levels.
  • il_estimate_prior() sets the prior match probability from deterministic matching rules, counting unique blocked pairs across overlapping rules, optionally from a deterministic record sample through record_sample_proportion.
  • il_prior_prevalence() and il_prior_m() add regularizing custom priors for EM, il_constrain_m() adds explicit fixed matched-class constraints, and il_priors() / il_constraints() expose the stored metadata.
  • il_estimate_m_from_labels() and il_estimate_m_from_column() initialize parameters from ground-truth labels.

Prediction

  • predict() supports both threshold (match probability) and threshold_match_weight (evidence-only log2 Bayes factor) filtering.
  • Prediction output includes evidence-only match_weight, prior-inclusive total_match_weight, and posterior match_probability.
  • predict(type = "weights") returns match weights on the log2 Bayes-factor scale, and greedy = TRUE adds deterministic one-to-one post-processing for link models.
  • include_fields = TRUE joins all source columns into the scored output.
  • collect = FALSE returns an il_compared_lazy object backed by a model-scoped in-database table.
  • il_score_missing_edges() enumerates and scores unscored within-cluster pairs.
  • il_score_pairs() scores every pair between two sets of records with a trained model, without blocking, using the model's own term-frequency tables.
  • il_score_patterns() scores compatible comparison-pattern tables, including dependency-aware pattern tables larger than the table used for fitting.
  • il_deterministic_link() performs single-table exact-match deduplication without training.
  • il_find_matches() scores a set of probe records against existing data.
  • profile_sql = TRUE on predict() attaches lightweight SQL timing metadata to collected predictions or lazy prediction objects, and lazy objects keep it when collected. Profiling adds no overhead when disabled.

Diagnostics and evaluation

  • il_parameters() and il_weights() expose the learned m/u parameters.
  • il_waterfall() decomposes a pair's match weight into per-comparison contributions.
  • il_training_history() tracks parameter convergence across EM iterations.
  • il_completeness() and il_profile() summarize data quality, and il_profile() accepts raw SQL expressions as column definitions (e.g., "city || left(first_name, 1)").
  • il_unlinkables() identifies records that cannot be linked under any blocking rule.
  • il_accuracy(), il_precision_recall(), and il_roc() evaluate performance against labeled data.
  • il_errors() surfaces false positives and false negatives.
  • il_graph_metrics() computes node degree, node centrality, cluster density, cluster centralization, and bridge detection.
  • il_comparison_vectors() returns the gamma pattern distribution from a trained model.

Data exploration

  • il_compare_records() computes comparison levels for one explicit record pair against a spec without fitting a model, and il_string_similarity() computes 5 string similarity metrics for a single pair.
  • il_comparator_score() computes batch string similarity across a data frame with SQL-side scoring on DuckDB.
  • il_comparator_threshold_chart() visualizes match rates at multiple similarity thresholds.
  • il_phonetic_chart() produces a Soundex agreement heatmap.
  • il_tf_chart() visualizes model-specific term frequency distributions with labeled most/least common values.
  • il_register_tf() registers pre-computed term frequency tables in the database and returns the updated model.

Visualization

  • autoplot() methods for il_model, il_compared, il_training_history, il_accuracy, il_roc, il_precision_recall, il_unlinkables, il_completeness, il_count_pairs, il_profile, il_string_similarity, il_comparator_score, and il_comparison_vectors.
  • All chart types are composable with standard ggplot2 layers.

Datasets

  • fake_1000: 1,000 records (250 entities) for deduplication.
  • fake_1000_labels: 3,176 pairwise labels for evaluation.
  • fake_20: minimal 20-record example.
  • febrl4a / febrl4b: 5,000-record cross-table linkage benchmark from FEBRL.

SQL backends and persistence

  • All computation runs inside a DBI-compatible database: DuckDB (recommended) or SQLite.
  • Database-backed workflows support zero-copy registration from dbplyr::tbl_lazy references and existing table names, in addition to in-memory data frames.
  • il_save() and il_load() support both RDS files and Splink settings JSON.
  • il_attach() reattaches a saved model to different data or connections.
  • il_cleanup() removes temporary tables owned by a single model, making it safe for shared DBI connections with multiple live models.
  • il_cleanup_all() removes all package-owned temporary tables from a connection for exploratory sessions and failed runs.

Performance

  • Gamma computation is pushed into DuckDB using native C++ string similarity functions.
  • SQLite is retained as a fallback with R-side gamma computation via stringdist.
  • DuckDB uses SQL-native connected components, with an igraph fallback for SQLite.
  • Term-frequency, lazy prediction, and scratch tables use generated model-scoped names to avoid collisions on shared connections.
  • profile_sql = TRUE on il_estimate_u(), il_estimate_prior(), and predict() records lightweight SQL timing metadata for performance investigation.
  • options(irelink.show_sql = TRUE) prints every SQL statement irelink sends to the database, formatted for reading.
  • End-to-end benchmarks against an R-side SQLite baseline: 1,000 records in 1.4 s (2.1× faster), 5,000 records in 19.5 s (1.6×), 10,000 records in 61.4 s (2.6×). Speedup grows with dataset size.

From NEWS.md in the release

Install

Health

CRAN checks
13OK
Slowest check: 7.5 min · r-release-macos-x86_64
Status changes
  • OK13 OKNow
  • OK6 OK2026-10-11
Advisories

none known

Documentation

In release 0.0.1
READMEYes · 417 wordsVignettesYes · 6 · dynamicNEWSYes · 67% structured · mentions 0.0.1Citation fileNoWebsiteYes
Help pages
128 (1 internal)includes a package overview page
Examples that run
100%102 run in a plain check
Exported functions with examples
92%
Documented parameters
96%
Return-value docs
100%
Help pages citing references
2%

Downloads

169
CRAN downloads in the past year
Rank #25,449 · ~0/day · ~14/mo
irelink
Daily download trend is not available in this view yet.
16930 days
16990 days
1691 year
Compare downloads with other packages →

Repository

4Stars
0Forks
0Open issues
0Open PRs
0Releases
177Commits
1Commit identities
177 commits · Last activity 2026-10-01
Responsiveness
not measured
PracticesBeta

Repository github.com/christopherkenny/irelink is linked, but repository-practices checks have not run for it yet.

How this is detected·Detection ruleset v3 (2026-09-26)

Dependencies

Declared dependencies
20 external dependencies (excludes base and recommended)

Installing irelink adds 26 packages (13 with compiled code, 21 MB of source tarballs). Heaviest: ggplot2 6.0 MB, duckdb 4.6 MB, isoband 1.5 MB.

Depends (1)
R >= 4.1.0
LinkingTo (0)
none
Enhances (0)
none
Reverse dependencies
0direct
0indirect

Nothing depends on this yet.

Datasets

People & History

People (8)
Author, Maintainer since 0.0.1 (2026), Copyright holder
Copyright holder
Copyright holder of splink
Copyright holder
Author of splink
Copyright holder
Author of splink
Copyright holder
Author of splink
Copyright holder
Lead author of splink, the Python package this is derived from
Copyright holder
Author of splink
Copyright holder
Author of splink
Releases (1)
  • 0.0.1Latest
    2026-10-10 · current release ·
    7 days in CRAN's queue
    Listed in CRAN's incoming queue from 2026-10-03 21:57 to 2026-10-10 10:19 UTC, in 29 readings.
  • R
    R 4.6.0 released · 2026-04-24
Across CRAN, the median accepted release of the past year spent 19 hours in the queue, 90% under 11 days.How queue time is measured

Package metadata

First published
2026-10-10
Total releases
1 / 1 yrs
License
MIT + file LICENSE OSI
Minimum R
≥ 4.1.0
Bundled data
312 KB / 5 files
Download size
751 KB

Cite

Cite this package

Run in R for the authors' preferred citation:

citation("irelink")

This package has no citation file, so citation() returns this entry built from DESCRIPTION.

Cite the R Observatory

For a number measured here: a download total, a coverage figure, an archival date.

From data release v2026-10-18, which the citation names so these numbers can be found later. More on citing and the projects behind them.

Report a problem with this page →

Privacy choices

These apply to this browser and are stored on this device only. Nothing about your choice is sent to us.

Read the privacy policy