knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
Phases 2-3 compare two extracted datasets by computing stratified prevalence ratios and synthesizing them via multi-level random-effects meta-analysis.
The pipeline has 4 steps, each producing a more aggregated table:
yearly concept x year x sex x age_group (raw PR per stratum) | v meta across years meta_agegroups concept x sex x age_group (pooled across years) | v meta across age groups meta_by_sex concept x sex (pooled across age groups) | v meta across sexes meta_summary concept (sex = "Both") (final summary)
library(syrona) # Both datasets must already be extracted (in data/sources/) compare_all("Hospital_A", "Hospital_B")
This loads both datasets, runs the 4-step pipeline for each domain present in both, and saves results to data/comparisons/Hospital_A_vs_Hospital_B/.
compare_all("Hospital_A", "Hospital_B", domains = "conditions")
You can also run each step individually for more control:
d1 <- load_dataset("Hospital_A") d2 <- load_dataset("Hospital_B") # Step 1: Yearly comparison (inner join on concept x year x sex x age_group) yearly <- compare_yearly(d1, d2, prev_table = "condition_prevalence") # Step 2: Meta across years meta_ag <- compare_meta_agegroups(yearly) # Step 3: Meta across age groups meta_sex <- compare_meta_by_sex(meta_ag) # Step 4: Meta across sexes meta_sum <- compare_meta_summary(meta_sex)
For each matched stratum, Syrona computes:
Log2 prevalence ratio:
log2_pr = log2(p2 / p1)
Where p1 and p2 are the prevalence values in dataset 1 (reference) and dataset 2 (comparison).
Standard error (on log2 scale):
SE = sqrt((1 - p1) / (p1 * n1) + (1 - p2) / (p2 * n2)) / ln(2)
Where n1 and n2 are the denominators (persons observed in that stratum).
95% confidence interval:
CI = log2_pr +/- 1.96 * SE
Significance: A stratum is significant if the CI excludes zero on the log2 scale (i.e., the fold difference excludes 1.0).
Each comparison table contains these columns:
| Column | Description |
|----|----|
| concept_id | OMOP concept ID |
| log2_pr | Log2 prevalence ratio |
| se | Standard error (log2 scale) |
| ci_low, ci_high | 95% CI bounds (log2 scale) |
| fold_diff | Natural-scale fold difference (2\^log2_pr) |
| fold_ci_low, fold_ci_high | Natural-scale CI bounds |
| fold_symmetric | max(fold, 1/fold) - useful for ranking |
| p_value | Two-sided p-value |
| sig | TRUE if CI excludes zero |
| meta_model_type | "Random-Effects", "Fixed-Effect", or "Pass-Through" |
| n_strata | Number of strata pooled |
| tau2 | Between-study variance (heterogeneity) |
| I2 | Percentage of variance due to heterogeneity |
| Q | Cochran's Q statistic |
| pval_Q | P-value for Q test |
For each group of strata to be pooled, Syrona uses this fallback strategy:
meta::metagen)The Paule-Mandel estimator is preferred because it handles small numbers of studies better than DerSimonian-Laird.
The meta-analysis cascade produces heterogeneity metrics at each aggregation level:
These metrics help identify concepts where the summary prevalence ratio masks meaningful variation across strata.
# List available comparisons list_comparisons() #> [1] "Hospital_A_vs_Hospital_B" # Load a comparison comp <- load_comparison("Hospital_A", "Hospital_B") names(comp) #> [1] "condition_yearly" "condition_meta_agegroups" #> [3] "condition_meta_by_sex" "condition_meta_summary"
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.