Name-Blind Variable-Role Detection by Data Signature
Overview
Deterministic, name-blind detection of variable roles (group, outcome, survival or duration time and event, coupled binary-continuous pairs, calendar time index, paired and agreement measurements, repeated measures and panels, scale and rating items, subject or entity identifier, covariate) in tabular data from any domain -- clinical, financial, social, experimental. Roles are assigned from each column's information-theoretic signature -- Shannon entropy, normalized mutual information, and distributional shape -- rather than from column names, so renaming columns to 'col_1', 'col_2', ... does not change the result ("Data inspice, non nomen"). An optional, capped name-based hint and automatic header-row detection are also provided. No large language models and no external data transmission. Extracted from the 'MDStatR' biostatistics engine; see Boynukara (2026) doi:10.5281/zenodo.20707791.
Corrections so that the package does what its documentation says, found by running it on
public survival data. Detection stays deterministic and name-blind.
New function: verify_roles()
verify_roles(data, claim)checks a declared assignment of roles against the name-blind value signature. Verdicts:contradicted(a falsification backed by a value statistic),consistent(a reading the data support, never "correct") andunverifiablewith sub-reasonidentifiability(design roles: group, outcome, covariate) orcoverage(no test exists, or the evidence is empty). Binary scale items are never consistent.contradictedis issued only for falsifications backed by a value statistic (exact list in?verify_roles); absence of a time-event association isunverifiable(coverage), not a contradiction. Each claimed pair is judged on its own, and a survival claim (time plus event) is one claim shown as two rows.unclaimedlists blind-found structure the claim does not state under the same role. Detectors are unchanged. See?verify_roles, the README and the vignette.
Show all changes in 0.3.0Hide the rest of the changes in 0.3.0
New function: harmonize_roles()
harmonize_roles(sites)aligns the roles detected name-blind in two or more sites (a named list of data.frames) into amap(role by site,aligned/partial/absent), descriptivechecksand asite_onlytable. Flags are categorical only:type_mismatch,coding_mismatch,size_mismatch; Jaccard and range overlap are reported but never flagged. The residualcovariaterole is excluded. Detectors are unchanged. See?harmonize_roles, the README and the vignette.
New role: coupled_pair
- The identifiable object in a dependent (binary, positive-continuous) pair is the PAIR itself; whether it is (survival time, event) or (cause, binary outcome) is design-relative and, in general, not a function of the joint distribution. The survival roles are now assigned only when censoring geometry singles the survival reading out: the continuous member is anchored at zero (mean - 2 sd <= 0), events sit strictly earlier than censorings, and the top time-tertile's event rate is strictly below the bottom's. Otherwise the new
coupled_pairrole reports the pair with both readings, and the user decides. Documented ceiling: a zero-anchored continuous cause whose larger values are protective still reads as survival. - A randomized-trial table (binary arm shifting a positive measurement) is therefore no longer reported as a survival pair: it becomes
coupled_pair. - **Dominance gate.** When two decisive pairs on DISJOINT time columns compete, the winner is assigned the survival roles only if its event-time association dominates at the 2-sigma universal (Fisher z two-correlation comparison); otherwise the pair is reported as
coupled_pairwith the competing reading named. A rival sharing the winner's time column agrees on the axis and merely offers another event candidate (a ranking question), and an ID-typed time candidate may win on its exceptional evidence bar but may not veto a structurally-typed reading.
Binary-outcome evidence: two-part MDL code
- The per-predictor 2-sigma dCor test behind
outcome_binaryis replaced by a Bernoulli MDL code: a candidate cause is admitted only when its one-slope logistic code -- or, for non-monotone dependence, a two-Gaussian split of the predictor by the outcome -- saves more bits than the slope's parameter cost (1/2 log2 n) PLUS the log2(m) model-index bits naming it among the m candidates (Rissanen two-part code). The naming term makes the evidence selection-consistent, so scanning many predictors on noise no longer buys phantom outcomes (~14% -> ~6% of pure-noise tables); a weak borderline cause now stays honestly silent instead.
Pass 5: derived deciders for group, pairs and ordinal scales
- **
group_var** is the character/factor column with the highest normalized Shannon entropy H/log2(k) (ties: fewer levels, then value fingerprint); a column with a level seen fewer than 3 times is not a candidate. The point table is gone. - **Paired vs agreement** is decided by the MDL shift bits of the best pair (bits saved by coding the difference with a free mean, net of one parameter): > 0 =>
paired_pairs, otherwiseagreement_pairs.potential_pairsnow carriesbitsandshift_bits. - **Ordinal
scale_items** are accepted when a one-factor Gaussian two-part code on the standardized candidate columns saves bits over independence (.mdl_factor_bits). score/max_score/pctare bits (max_scoreNA) for derived roles and points for the ported ones.- **Measured and rejected, kept on ported scorers:** survival admission/rank by association bits, wide
repeated_measuresas a one-factor block (false positives rose from 15 to 163-207 tables), and a derived binary-item scale criterion (it rejected every simulated binary battery) each regressed false positives or recall and were reverted. Survival, widerepeated_measuresand binaryscale_itemstherefore remain on point scorers.
Domain generalization (finance and beyond)
- **New role
time_index.** Date/POSIXct columns -- and character columns whose every value parses as a date -- type as Datetime and are reported as calendar axes. They were previously typed "Other" and invisible to every detector. The class and format are properties of the values, so name-blindness is preserved. - **Panel entity/time axis.** On a balanced long panel both axis readings satisfy the structural test. Serial dependence of the measures along the candidate time axis (2-sigma) now picks the entity; when nothing discriminates, the panel is reported with its admissible axis readings (
repeated_measures$panel_axes) andsubject_idstays silent. A Datetime column can be the panel time axis. - **Short rating batteries.** A battery of exactly 3-4 ordinal items (e.g. multi-agency credit ratings) is now scoreable as
scale_items, guarded by the pairwise 2-sigma dependence gate; the >= 5-item path is unchanged. - **Finance keyword dictionary.**
rolescry_default_name_bonus(domain = "finance")(or"all"); the default"clinical"is unchanged. The name channel remains optional and capped. - README, DESCRIPTION and examples reworded domain-neutrally.
Behavior changes
- **Logical event columns.** A TRUE/FALSE column now value-types as Binary; it was typed "Other" and silently excluded from every survival and outcome candidate set.
- **Sink veto in repeated measures.** A column MDL-explained by two or more mutually independent other block members is a dependency sink (collider), not a repeated measurement, and is removed from the block.
y = x1 + x2 + noiseis no longer swallowed as a correlated block, so the continuous outcome can be detected. - **
covariateis now the residual role.** It lists the continuous, categorical and binary columns that no other role claimed. In 0.2.0 it listed every such column, including the survival pair, the group and the outcomes. - **Survival pairs are compared on common rows.** Every admissible time/event pair is re-evaluated on the rows complete in all candidate columns. Previously each pair was judged on its own available cases, so a pair whose columns were missing in different rows could win on a different subsample (e.g.
survival::lung). - **Integer follow-up times.** An all-distinct positive integer column (which value-types as an identifier) is now a survival-time candidate. Because this overturns the identifier typing, it must pass both association tests (monotone MDL and the dCor independence test), not either one (e.g.
survival::ovarian). - **Subject id atomicity.** A column already assigned to a survival role is no longer also reported as
subject_id.
Bug fixes
- The KSG mutual-information estimator returned
NaNon tied values (a neighbor count of -1 passed todigamma()), which made the dependence measureNaNand emitted warnings (e.g.survival::pbc). Counts are now clamped at zero. - Correlation calls on constant columns in the paired/agreement scorers no longer emit "standard deviation is zero" warnings; the result is unchanged (
NA).
Documentation
- The README quick-start example now uses data in which the documented roles are actually present, and a "Known limitations" section was added.
?detect_rolesstates that roles can overlap, thatcovariateis residual, and that a role is reported as not found rather than guessed.
From NEWS.md in the release
Install
Health
ERRORtestsr-oldrel-macos-arm64, r-release-macos-arm64
r-oldrel-macos-arm64
Running ‘spelling.R’ [0s/1s]
Running ‘testthat.R’ [7s/8s]
Running the tests in ‘tests/testthat.R’ failed.
Complete output:
> library(testthat)
> library(rolescry)
>
> test_check("rolescry")
Saving _problems/test-name-blind-21.R
[ FAIL 1 | WARN 0 | SKIP 0 | PASS 356 ]
══ Failed tests ════════════════════════════════════════════════════════════════
── Failure ('test-name-blind.R:21:3'): outcome_binary is detected name-blind; name_bonus agrees with a decisive math pick ──
Expected `pure$roles$outcome_binary$columns` to be identical to "death".
Differences:
`actual`: "male"
`expected`: "death"
[ FAIL 1 | WARN 0 | SKIP 0 | PASS 356 ]
Error:
! Test failures.
Execution haltedr-release-macos-arm64
Running ‘spelling.R’ [0s/0s]
Running ‘testthat.R’ [4s/4s]
Running the tests in ‘tests/testthat.R’ failed.
Complete output:
> library(testthat)
> library(rolescry)
>
> test_check("rolescry")
Saving _problems/test-name-blind-21.R
[ FAIL 1 | WARN 0 | SKIP 0 | PASS 356 ]
══ Failed tests ════════════════════════════════════════════════════════════════
── Failure ('test-name-blind.R:21:3'): outcome_binary is detected name-blind; name_bonus agrees with a decisive math pick ──
Expected `pure$roles$outcome_binary$columns` to be identical to "death".
Differences:
`actual`: "male"
`expected`: "death"
[ FAIL 1 | WARN 0 | SKIP 0 | PASS 356 ]
Error:
! Test failures.
Execution halted- ERROR11 OK, 2 ERRORNow
- ERROR12 OK, 1 ERROR2026-10-21
- OK13 OK2026-08-04
- NOTE12 OK, 1 NOTE2026-08-01
- OK6 OK2026-06-23
Documentation
- Help pages
- 8 (1 internal)includes a package overview page
- Examples that run
- 100%7 run in a plain check
- Exported functions with examples
- 100%
- Documented parameters
- 100%
- Return-value docs
- 100%
- Help pages citing references
- 0%
Downloads
Repository
Stars over time
Releases over time
Commits over time
3 development-tooling and community-health practices detected across 2 families in the upstream repository
Checks run against github.com/canboynukara/rolescry on 2026-10-21.
This repository shows signs of AI coding tools.
- Claude Codefirst seen 2026-06-28Commits: at least 4 crediting it in the message
- Claude Opus 53 commits · Jul 2026
- Claude Opus 4.81 commit · Jun 2026
Dependencies
Installing rolescry adds no packages beyond those that come with R.
Code & Tests
People & History
Package metadata
- First published
- 2026-06-22
- Total releases
- 3 / 1 yrs
- License
- Apache License (== 2.0)
- Minimum R
- ≥ 4.0.0
- Download size
- 103 KB
Cite
Cite this package
Run in R for the authors' entry:
citation("rolescry")The package provides a citation file, so citation() returns the authors' own entry.
It points to 10.5281/zenodo.21003941, 10.5281/zenodo.20707791.
The repository also keeps a CITATION.cff.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-24, which the citation names so these numbers can be found later. More on citing and the projects behind them.