Install
$ agentstack add skill-choxos-biostatagent-real-world-evidence ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Real-World Evidence Analysis in R
Overview
Methods for analyzing real-world data (RWD) to generate real-world evidence (RWE). Covers target trial emulation, comparative effectiveness research, propensity score methods for observational data, external control arms, bias quantification, and sensitivity analysis for unmeasured confounding.
Target Trial Emulation
Conceptual Framework
# Target trial emulation framework
# Specify the target trial protocol, then emulate using observational data
# Key elements to specify:
# 1. Eligibility criteria
# 2. Treatment strategies
# 3. Assignment procedures
# 4. Follow-up period
# 5. Outcome
# 6. Causal contrast (ITT, per-protocol, etc.)
# 7. Analysis plan
Using TrialEmulation Package
library(TrialEmulation)
# Prepare data for target trial emulation
# Data should be in long format with time-varying covariates
# Example: Clone-censor-weight approach
trial_data
group_by(patient_id) |>
mutate(
# Check eligibility at each visit
eligible = check_eligibility(age, lab_values, prior_treatment),
# Time zero for each potential trial
trial_start = if_else(eligible & treatment_initiated, visit_date, NA)
) |>
ungroup()
# Step 2: Clone patients for each trial they're eligible for
# Step 3: Apply artificial censoring per assigned strategy
# Step 4: Weight for selection and artificial censoring
# Step 5: Pool and analyze
Propensity Score Methods for RWE
Propensity Score Estimation
library(MatchIt)
library(WeightIt)
library(cobalt)
# Estimate propensity scores
ps_model select(age, sex, bmi, smoking, diabetes, baseline_egfr),
Q.SL.library = c("SL.glm", "SL.ranger", "SL.xgboost"),
g.SL.library = c("SL.glm", "SL.ranger"),
k_split = 5,
verbose = FALSE
)
aipw_result$fit()$summary()
# Risk difference and risk ratio
aipw_result$summary()
External Control Arms
Historical Controls Integration
# Combine trial data with external controls
# Step 1: Identify comparable external controls
external_controls
filter(
# Match eligibility criteria
age >= 18 & age = 30,
no_prior_treatment == TRUE
)
# Step 2: Propensity score matching/weighting
library(MatchIt)
combined mutate(source = "trial", treatment = treatment),
external_controls |> mutate(source = "external", treatment = 0)
)
# Match external controls to trial control arm characteristics
match_ext filter(treatment == 0 | source == "external"),
method = "nearest",
caliper = 0.2
)
# Step 3: Analysis with matched external controls
matched_combined
group_by(patient_id) |>
mutate(
p_uncensored = 1 - predict(cens_model, type = "response"),
ipcw = cumprod(p_uncensored)
) |>
ungroup()
# Stabilized weights
rwd_long
mutate(
sw = ps_weight * ipcw / mean(ps_weight * ipcw, na.rm = TRUE)
)
# Weighted analysis with stabilized weights
library(survey)
design_ipcw
filter(adjusted_effect
summarise(across(everything(), ~mean(!is.na(.)) * 100)) |>
pivot_longer(everything(), names_to = "variable", values_to = "pct_complete")
# 2. Plausibility
plausibility_checks
summarise(
age_range_ok = all(age >= 0 & age = admission_date, na.rm = TRUE),
lab_in_range = all(egfr >= 0 & egfr
count(year = year(index_date)) |>
ggplot(aes(year, n)) +
geom_col() +
labs(title = "Patient Enrollment Over Time")
# 4. Treatment patterns
rwd |>
group_by(treatment) |>
summarise(
n = n(),
mean_age = mean(age),
pct_male = mean(sex == "male") * 100,
mean_followup = mean(followup_time)
)
Reporting RWE Studies
# Create Table 1 for RWE study
library(tableone)
# Unweighted baseline characteristics
vars <- c("age", "sex", "bmi", "smoking", "diabetes", "egfr", "stage")
cat_vars <- c("sex", "smoking", "diabetes", "stage")
tab1_unweighted <- CreateTableOne(
vars = vars,
strata = "treatment",
data = rwd,
factorVars = cat_vars,
test = FALSE
)
# Weighted baseline characteristics (after PS weighting)
tab1_weighted <- svyCreateTableOne(
vars = vars,
strata = "treatment",
data = design_weighted,
factorVars = cat_vars,
test = FALSE
)
# Print with SMD
print(tab1_unweighted, smd = TRUE)
print(tab1_weighted, smd = TRUE)
Key Packages Summary
| Package | Purpose | |---------|---------| | TrialEmulation | Target trial emulation | | WeightIt | Propensity score weighting | | MatchIt | Propensity score matching | | cobalt | Balance diagnostics | | AIPW | Doubly robust estimation | | adjustedCurves | Adjusted survival curves | | tipr | Tipping point analysis | | EValue | E-values for unmeasured confounding | | ipw | Inverse probability weighting | | episensr | Quantitative bias analysis |
Best Practices
- Protocol first: Define target trial before touching data
- Eligibility: Apply strict, transparent eligibility criteria
- Time zero: Align treatment initiation with follow-up start
- Immortal time: Avoid immortal time bias in study design
- Balance: Check and report covariate balance (SMD < 0.1)
- Positivity: Assess overlap and address violations
- Sensitivity: Quantify impact of unmeasured confounding
- Reporting: Follow RECORD/STROBE-RWE guidelines
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: choxos
- Source: choxos/BiostatAgent
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.