The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Package {rwevalidate}


Title: Validate Patient Cohorts for Real-World Evidence Studies on the OMOP Common Data Model
Version: 0.1.2
Description: Validates instantiated patient cohorts on an Observational Medical Outcomes Partnership (OMOP) Common Data Model (CDM) database for real-world-evidence (RWE) studies. From a single function call it produces a structured validation report in Hypertext Markup Language (HTML) and JavaScript Object Notation (JSON) covering concept coverage, cohort attrition, temporal data density, and covariate feasibility against a comparator. The checks are aligned with the United States Food and Drug Administration (FDA) guidance on real-world data and evidence, FDA (2023) https://www.fda.gov/media/171667/download, the Harmonized Protocol Template to Enhance Reproducibility (HARPER), Wang and others (2022) <doi:10.1002/pds.5507>, and the Reporting of Studies Conducted Using Observational Routinely-Collected Data for Pharmacoepidemiology (RECORD-PE) statement, Langan and others (2018) <doi:10.1136/bmj.k3532>. A self-contained example database is bundled so the checks can be run without a live database connection.
License: MIT + file LICENSE
URL: https://github.com/tavakohr/rwevalidate
BugReports: https://github.com/tavakohr/rwevalidate/issues
Encoding: UTF-8
Language: en-US
Depends: R (≥ 4.1)
Imports: DBI, RPostgres, jsonlite, rmarkdown, glue, cli, utils
Suggests: testthat (≥ 3.0.0), duckdb, ggplot2, knitr, covr
VignetteBuilder: knitr
Config/testthat/edition: 3
Config/roxygen2/version: 8.0.0
NeedsCompilation: no
Packaged: 2026-07-11 17:23:20 UTC; tavak
Author: Hamid Tavakoli [aut, cre]
Maintainer: Hamid Tavakoli <htavakoli@gmail.com>
Repository: CRAN
Date/Publication: 2026-07-21 10:20:02 UTC

Build the traffic-light validation summary table

Description

Collects each module's flags into one row per validation section, mapping to the regulatory framework the section addresses.

Usage

build_check_summary(results)

Arguments

results

The combined results list (named module outputs, e.g. attrition, density). Modules absent from the list are skipped.

Value

A data.frame with columns section, status, maps_to, detail.


Connect to an OMOP CDM database

Description

Opens a PostgreSQL connection via RPostgres and validates that the required clinical tables (person, observation_period, condition_occurrence, drug_exposure, measurement, visit_occurrence, death) exist in cdm_schema and the vocabulary tables (concept, concept_ancestor) exist in vocab_schema before returning. For split-schema CDMs (clinical and vocabulary in different schemas) pass vocab_schema; it defaults to cdm_schema for single-schema builds.

Usage

cdm_connect(
  host = "localhost",
  port = 5432,
  dbname,
  user,
  password,
  cdm_schema,
  vocab_schema = cdm_schema
)

Arguments

host

Database host. Default "localhost".

port

Database port. Default 5432.

dbname

Database name.

user

Database user.

password

Database password.

cdm_schema

Schema holding the clinical CDM tables.

vocab_schema

Schema holding the vocabulary tables. Defaults to cdm_schema.

Value

A live DBI connection to the CDM database.

Examples

## Not run: 
# Requires a live PostgreSQL OMOP CDM server and real credentials, so this
# cannot be executed during checks. For a runnable, database-free demo of
# the package, see example_cdm() and validate_cohort().
con <- cdm_connect(
  dbname = "omop", user = "me", password = "secret",
  cdm_schema = "mimiciv_omop", vocab_schema = "vocab"
)
cdm_disconnect(con)

## End(Not run)


Disconnect from a CDM database

Description

Disconnect from a CDM database

Usage

cdm_disconnect(con)

Arguments

con

A live DBI connection returned by cdm_connect().

Value

Invisibly returns the result of DBI::dbDisconnect().

Examples

# Works on any DBI connection, demonstrated here on the bundled in-memory
# DuckDB example CDM (no database server needed).
if (requireNamespace("duckdb", quietly = TRUE)) {
  con <- example_cdm()
  cdm_disconnect(con)
}


Classify a vector of module flags into a traffic-light status

Description

Flags are strings prefixed "FAIL:" or "WARN:" (see the module functions). Any FAIL -> "fail" (red); else any WARN -> "warn" (amber); else "pass" (green).

Usage

classify_status(flags)

Arguments

flags

Character vector of flag messages (may be empty).

Value

A single string: "pass", "warn", or "fail".


Create a small in-memory OMOP CDM for examples and demos

Description

Builds a tiny synthetic OMOP CDM (20 persons) in an in-memory DuckDB database and returns a live connection. Every table rwevalidate queries for the concept, attrition, density, and covariate modules is populated, together with a cohort table that has the standard subject_id, cohort_definition_id, cohort_start_date, and cohort_end_date columns. The cohort table carries two arms so all four modules can be demonstrated: persons 1-10 are the target cohort (cohort_definition_id = 1) and persons 11-20 are a comparator (cohort_definition_id = 2). The clinical tables and a minimal vocabulary both live in the default main schema.

Usage

example_cdm()

Details

This exists so the package can be tried, and its examples can run, without a live database connection. It is a synthetic demo fixture, not a substitute for a real CDM. The duckdb package (a soft dependency) must be installed. The caller owns the returned connection and should close it with cdm_disconnect().

Value

A live DBI connection to an in-memory DuckDB OMOP CDM.

Examples

if (requireNamespace("duckdb", quietly = TRUE)) {
  con <- example_cdm()
  attrition <- run_attrition(con, cdm_schema = "main",
                             cohort_table = "cohort", cohort_id = 1,
                             vocab_schema = "main")
  print(attrition$cohort_size)
  cdm_disconnect(con)
}


Render the validation report (HTML) and write the JSON sidecar

Description

Renders the bundled R Markdown template to a self-contained HTML report and writes a machine-readable validation_results.json alongside it.

Usage

render_validation_report(
  results,
  output_dir,
  cdm_schema,
  cohort_id,
  package_version = as.character(utils::packageVersion("rwevalidate")),
  run_date = Sys.time(),
  quiet = TRUE
)

Arguments

results

Combined results list (e.g. list(attrition = ..., density = ...), optionally data_source = ...).

output_dir

Directory to write the report into (created if needed).

cdm_schema

CDM schema name (for the report header / JSON).

cohort_id

Cohort definition id (for the report header / JSON).

package_version

Package version string. Defaults to the installed rwevalidate version.

run_date

Timestamp for the run. Defaults to base::Sys.time().

quiet

Passed to rmarkdown::render(). Default TRUE.

Value

Invisibly, a list with html, json, and check_summary.


Module 2 - Cohort Attrition Audit

Description

Profiles an instantiated cohort: size, index-date distribution, prior observation coverage, and demographics at index. Maps to HARPER section 5 and RECORD-PE item 6. All thresholds are arguments.

Usage

run_attrition(
  con,
  cdm_schema,
  cohort_table,
  cohort_id,
  obs_window = c(-365, 0),
  vocab_schema = "vocab",
  obs_warn_pct = 70,
  obs_fail_pct = 50,
  attrition_warn_threshold = 0.5
)

Arguments

con

A live DBI connection (see cdm_connect()).

cdm_schema

Schema holding the clinical CDM tables (e.g. "mimic_cdm").

cohort_table

Cohort table, schema-qualified (e.g. "results.rwevalidate_test_cohort"). Must have columns subject_id, cohort_definition_id, cohort_start_date, cohort_end_date.

cohort_id

Integer cohort definition id to profile.

obs_window

Length-2 numeric c(pre, post) in days relative to index. The required prior-observation window is abs(obs_window[1]) days (default 365).

vocab_schema

Schema holding the vocabulary tables (concept). In this split-schema environment the clinical schema's concept table is empty, so the gender label is resolved from vocab_schema. Default "vocab".

obs_warn_pct, obs_fail_pct

Prior-observation coverage thresholds (percent of cohort with sufficient prior observation). Below obs_warn_pct flags WARN, below obs_fail_pct flags FAIL. Defaults 70 and 50.

attrition_warn_threshold

Reserved for stepwise inclusion-criteria attrition (single-criterion drop fraction). Not exercised in v0.1 because criteria lists are not yet a supported input. Default 0.5.

Details

This profiles the cohort as it was handed in. It reports the cohort-level counts that item 6 asks for, but it does not yet rebuild a step-by-step attrition flowchart (how many subjects each inclusion or exclusion criterion removed), because the cohort table does not carry the criteria that built it. Per-criterion attrition is planned for a later version.

Value

A named list:

cohort_size

integer - distinct subjects in the cohort

index_date_summary

data.frame of index_year, n

obs_coverage

data.frame: cohort_n, n_sufficient, pct_sufficient, min_prior_days. cohort_n counts every cohort subject. A subject whose index date falls outside any observation period counts as insufficient prior observation rather than being dropped, so cohort_n matches cohort_size.

demographics

data.frame: sex, mean_age, min_age, max_age, n

flags

character vector of ⁠WARN:⁠/⁠FAIL:⁠ messages (empty if all pass)

Examples

if (requireNamespace("duckdb", quietly = TRUE)) {
  con <- example_cdm()
  res <- run_attrition(con, cdm_schema = "main", cohort_table = "cohort",
                       cohort_id = 1, vocab_schema = "main")
  res$cohort_size
  res$demographics
  cdm_disconnect(con)
}


Module 1 - Concept Coverage

Description

Profiles whether the cohort-defining concepts are present, well-mapped, and richly represented in the CDM. Maps to FDA RWE Relevance (are the data fit for the question?). This is the first module to read the vocabulary schema.

Usage

run_concepts(
  con,
  cdm_schema,
  cohort_table = NULL,
  cohort_id = NULL,
  concept_ids,
  domain = "condition",
  vocab_schema = "vocab",
  prevalence_warn_pct = 10,
  prevalence_fail_pct = 1,
  unmapped_warn_pct = 20
)

Arguments

con

A live DBI connection (see cdm_connect()).

cdm_schema

Schema holding the clinical CDM tables.

cohort_table

Cohort table, schema-qualified. Optional and currently unused; reserved for cohort-restricted prevalence in a later version.

cohort_id

Integer cohort definition id. Optional and reserved, see cohort_table.

concept_ids

Numeric vector of cohort-defining seed concept id(s). Their descendants are expanded via ⁠{vocab_schema}.concept_ancestor⁠.

domain

Domain the seed concepts live in; one of the names of the internal domain map ("condition", "drug", "measurement", "procedure"). Default "condition".

vocab_schema

Schema holding the vocabulary tables. Default "vocab".

prevalence_warn_pct, prevalence_fail_pct

Concept-prevalence thresholds (percent of CDM persons with at least one descendant record). Below warn flags WARN, below fail flags FAIL. Defaults 10 and 1.

unmapped_warn_pct

Per-domain unmapped-record threshold (percent mapped to concept_id = 0) above which a WARN is flagged. Default 20.

Value

A named list:

prevalence

data.frame: n_with, n_total, pct

ancestor_coverage

data.frame: total_descendants, present_descendants, pct_present

mapping_by_domain

data.frame: domain, n_records, n_unmapped, pct_mapped

flags

character vector of ⁠WARN:⁠/⁠FAIL:⁠ messages

Examples

if (requireNamespace("duckdb", quietly = TRUE)) {
  con <- example_cdm()
  # 316139 = "Heart failure" (SNOMED), the seed concept in the demo CDM.
  res <- run_concepts(con, cdm_schema = "main", concept_ids = 316139,
                      domain = "condition", vocab_schema = "main")
  res$prevalence
  res$mapping_by_domain
  cdm_disconnect(con)
}


Module 4 - Covariate Feasibility

Description

Compares a target cohort against a comparator on baseline covariates: standardized mean differences (SMD love-plot data), a per-arm prevalence table, and a simple power calculation. Maps to HARPER Sec.4 (comparability). Runs only when a comparator_id is supplied.

Usage

run_covariates(
  con,
  cdm_schema,
  cohort_table,
  cohort_id,
  comparator_id,
  vocab_schema = "vocab",
  covariate_window = c(-365, 0),
  top_n = 20,
  smd_warn_threshold = 0.1,
  power_baseline_rate = 0.15,
  power_effect_rate = 0.3,
  power_sig_level = 0.05,
  power_warn_threshold = 0.8
)

Arguments

con

A live DBI connection (see cdm_connect()).

cdm_schema

Schema holding the clinical CDM tables.

cohort_table

Cohort table, schema-qualified, containing both arms.

cohort_id

Integer cohort definition id of the target arm.

comparator_id

Integer cohort definition id of the comparator arm.

vocab_schema

Schema holding the vocabulary tables. Default "vocab".

covariate_window

Length-2 numeric c(pre, post) days defining the baseline window relative to index for comorbidity/drug covariates. Default c(-365, 0).

top_n

Number of top conditions/drugs to profile. Default 20.

smd_warn_threshold

Absolute SMD above which a covariate is flagged imbalanced. Default 0.1 (standard).

power_baseline_rate, power_effect_rate

Assumed comparator and target event rates for the two-proportion power calculation. Defaults 0.15, 0.30.

power_sig_level

Significance level for the power calculation. Default 0.05.

power_warn_threshold

Power below this value flags a WARN. Default 0.80.

Value

A named list: smd_table, prevalence_table, power, flags.

Examples

if (requireNamespace("duckdb", quietly = TRUE)) {
  con <- example_cdm()
  # The demo CDM ships two arms: target = 1, comparator = 2.
  res <- run_covariates(con, cdm_schema = "main", cohort_table = "cohort",
                        cohort_id = 1, comparator_id = 2, vocab_schema = "main")
  res$smd_table
  res$power
  cdm_disconnect(con)
}


Module 3 - Temporal Data Density

Description

Profiles longitudinal data accrual around the index date: record density per patient per month across clinical domains, and follow-up completeness with a censoring-reason breakdown. Maps to FDA RWE Reliability (data accrual).

Usage

run_density(
  con,
  cdm_schema,
  cohort_table,
  cohort_id,
  obs_window = c(-365, 365),
  sparse_warn_min = 1
)

Arguments

con

A live DBI connection (see cdm_connect()).

cdm_schema

Schema holding the clinical CDM tables (e.g. "mimic_cdm").

cohort_table

Cohort table, schema-qualified.

cohort_id

Integer cohort definition id.

obs_window

Length-2 numeric c(pre, post) in days relative to index. Density is computed for records inside ⁠[index + pre, index + post]⁠. Default c(-365, 365).

sparse_warn_min

Minimum total records a domain must have within the window before it is considered present; domains below this flag WARN (likely missing/sparse domain). Default 1 (flag only truly empty domains).

Value

A named list:

density_by_domain

data.frame: domain, months_from_index, n_patients, n_records, records_per_patient

followup_summary

data.frame: one row per censoring_reason with n and median_followup_days (median over that group)

followup_detail

per-subject data.frame: subject_id, effective_end_date, followup_days, censoring_reason

flags

character vector of ⁠WARN:⁠/⁠FAIL:⁠ messages

Examples

if (requireNamespace("duckdb", quietly = TRUE)) {
  con <- example_cdm()
  res <- run_density(con, cdm_schema = "main", cohort_table = "cohort",
                     cohort_id = 1)
  head(res$density_by_domain)
  res$followup_summary
  cdm_disconnect(con)
}


Validate a patient cohort for real-world-evidence use

Description

One-call entry point: connects to the OMOP CDM (or uses a supplied connection), runs the attrition (Module 2) and temporal-density (Module 3) checks, and produces a self-contained HTML report plus a JSON sidecar aligned with FDA RWE and HARPER frameworks.

Usage

validate_cohort(
  cdm_schema,
  cohort_table,
  cohort_id = 1,
  con = NULL,
  vocab_schema = "vocab",
  concept_ids = NULL,
  concept_domain = "condition",
  comparator_id = NULL,
  obs_window = c(-365, 0),
  density_window = c(-365, 365),
  output_dir = "./validation_report",
  host = "localhost",
  port = 5432,
  dbname = NULL,
  user = NULL,
  password = NULL,
  render_html = TRUE,
  quiet = TRUE
)

Arguments

cdm_schema

Schema holding the clinical CDM tables (e.g. "mimic_cdm").

cohort_table

Cohort table, schema-qualified (e.g. "results.rwevalidate_test_cohort").

cohort_id

Integer cohort definition id. Default 1.

con

Optional open DBI connection. If NULL (default) one is opened from the connection arguments and closed on exit.

vocab_schema

Schema holding the vocabulary tables. Default "vocab". Required because the clinical schema's concept table may be empty in split-schema builds.

concept_ids

Optional numeric vector of cohort-defining seed concept id(s). When supplied, Module 1 (concept coverage) runs and populates report Section 2. When NULL (default) Module 1 is skipped.

concept_domain

Domain the seed concepts live in ("condition", "drug", "measurement", "procedure"). Default "condition".

comparator_id

Optional integer cohort definition id of a comparator arm. When supplied, Module 4 (covariate feasibility) runs and populates report Section 5. When NULL (default) Module 4 is skipped.

obs_window

Length-2 numeric c(pre, post) days for attrition prior observation. Default c(-365, 0).

density_window

Length-2 numeric c(pre, post) days for density. Default c(-365, 365).

output_dir

Directory for the report + JSON. Default "./validation_report".

host, port, dbname, user, password

PostgreSQL connection arguments, used only when con is NULL.

render_html

Render the HTML report. Default TRUE. If Pandoc is unavailable, only the JSON sidecar is written (with a warning).

quiet

Passed to rmarkdown::render(). Default TRUE.

Details

Supply either an open con (e.g. for DuckDB testing) or PostgreSQL connection arguments (dbname, user, password, ...). Connections opened internally are closed on exit; a connection passed in via con is left open.

Against a live PostgreSQL OMOP CDM, a typical call looks like:

validate_cohort(
  cdm_schema   = "mimic_cdm",
  cohort_table = "results.rwevalidate_test_cohort",
  cohort_id    = 1,
  dbname = "FHIR", user = "me", password = "secret",
  vocab_schema = "vocab",
  output_dir   = "./validation_report"
)

Value

Invisibly, a list with results (module outputs + data_source), report (paths + check summary), and flags (all collected flags).

Examples

# Runnable demo on a small in-memory DuckDB CDM (no database needed).
# render_html = FALSE writes only the JSON sidecar, so Pandoc is not required.
if (requireNamespace("duckdb", quietly = TRUE)) {
  con <- example_cdm()
  out <- validate_cohort(
    cdm_schema   = "main",
    cohort_table = "cohort",
    cohort_id    = 1,
    con          = con,
    vocab_schema = "main",
    output_dir   = tempfile("rwe_demo_"),
    render_html  = FALSE
  )
  print(out$report$check_summary)
  cdm_disconnect(con)
}


Write the JSON sidecar (no rendering)

Description

Exposed separately so results can be persisted even when Pandoc is unavailable for HTML rendering.

Usage

write_results_json(
  results,
  output_dir,
  cdm_schema,
  cohort_id,
  package_version = as.character(utils::packageVersion("rwevalidate")),
  run_date = Sys.time(),
  check_summary = NULL
)

Arguments

results

Combined results list (e.g. list(attrition = ..., density = ...), optionally data_source = ...).

output_dir

Directory to write the report into (created if needed).

cdm_schema

CDM schema name (for the report header / JSON).

cohort_id

Cohort definition id (for the report header / JSON).

package_version

Package version string. Defaults to the installed rwevalidate version.

run_date

Timestamp for the run. Defaults to base::Sys.time().

check_summary

Optional pre-built summary; rebuilt if NULL.

Value

The path to the written JSON file (invisibly).

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.