Calculate Simple (Stratum-Specific) Effects from a Joint Variable Model
Source:R/inteffects.R
inteffects.RdReplicates the output of an interaction-term model (e.g., simple effects from `publish()` or `emmeans`) by calculating all stratum-specific comparisons from a joint-variable model. Allows output on log or ratio scale with consistent column structure, including scale-appropriate standard errors.
Usage
inteffects(
joint_model,
joint_var_name,
factor1_name,
factor2_name,
factor1_levels,
factor2_levels,
level_separator = ".",
scale = c("ratio", "log"),
digits = 2,
conf.level = 0.95
)Arguments
- joint_model
A fitted model object (e.g., `svycoxph`, `svyglm`) that used a combined joint variable (e.g., `~ A_B`).
- joint_var_name
Character string. The name of the joint variable as used in the model formula (e.g., `"Race1_ObeseStatus"`).
- factor1_name
Character string. The name of the *first* logical factor used to create the joint variable (e.g., `"Race1"`). Used for naming output rows.
- factor2_name
Character string. The name of the *second* logical factor used to create the joint variable (e.g., `"ObeseStatus"`). Used for naming output rows.
- factor1_levels
Character vector. All levels of the *first* logical factor, with the reference level *first*.
- factor2_levels
Character vector. All levels of the *second* logical factor, with the reference level *first*.
- level_separator
Character string. The separator used to create the joint level names (e.g., `"_"` or `"."`). Default is `"."` (the R default for `interaction()`).
- scale
Character string. The scale for the output estimates, CIs, and SE. Options are `"ratio"` (default, e.g., OR/HR) or `"log"` (log-OR/log-HR).
- digits
Integer. Number of decimal places for rounding estimates, SE, and CIs when `scale = "ratio"`. Default is 2. (Set to NULL for no rounding).
- conf.level
Confidence level for the interval (default 0.95).
Value
A `tibble` (data frame) with columns:
`Comparison`: A description of the simple effect, styled similarly to the `Publish` package (e.g., "ObeseStatus(Obese vs Not Obese): Race1(White)").
`Estimate`: The point estimate on the specified `scale`.
`SE`: The standard error on the specified `scale`. Calculated using the delta method for `scale = "ratio"`.
`CI.low`: The lower bound of the confidence interval (on the specified `scale`).
`CI.upp`: The upper bound of the confidence interval (on the specified `scale`).
`p_value`: The p-value for the simple effect (tests H0: logEstimate=0 or Estimate=1).
Examples
# \donttest{
# --- Load required libraries for the example ---
if (requireNamespace("survey", quietly = TRUE) &&
requireNamespace("NHANES", quietly = TRUE) &&
requireNamespace("dplyr", quietly = TRUE) &&
requireNamespace("tidyr", quietly = TRUE) &&
requireNamespace("msm", quietly = TRUE)) { # msm needed for SE calculation
library(survey)
library(NHANES)
library(dplyr)
library(tidyr)
library(msm) # Load msm
# --- 1. Data Preparation (NHANES Example) ---
data(NHANESraw)
vars_needed <- c("Age", "Race1", "BPSysAve", "BMI", "ObeseStatus", "Hypertension_130",
"SDMVPSU", "SDMVSTRA", "WTMEC2YR")
nhanes_adults_processed <- NHANESraw %>%
filter(Age >= 20) %>%
mutate(
ObeseStatus = factor(ifelse(BMI >= 30, "Obese", "Not Obese"),
levels = c("Not Obese", "Obese")),
Hypertension_130 = factor(ifelse(BPSysAve >= 130, "Yes", "No"),
levels = c("No", "Yes")),
Race1 = relevel(as.factor(Race1), ref = "White")
) %>%
select(all_of(vars_needed)) %>%
drop_na()
adult_design_binary <- svydesign(
id = ~SDMVPSU, strata = ~SDMVSTRA, weights = ~WTMEC2YR,
nest = TRUE, data = nhanes_adults_processed
)
# --- 2. Create Joint Variable and Fit Joint Model ---
adult_design_binary <- update(adult_design_binary,
Race1_ObeseStatus = interaction(Race1, ObeseStatus, sep = "_", drop = TRUE)
)
adult_design_binary <- update(adult_design_binary,
Race1_ObeseStatus = relevel(Race1_ObeseStatus, ref = "White_Not Obese")
)
joint_model_logit <- svyglm(
Hypertension_130 ~ Race1_ObeseStatus + Age,
design = adult_design_binary, family = quasibinomial()
)
# --- 3. Run the function ---
f1_levels <- levels(adult_design_binary$variables$Race1)
f2_levels <- levels(adult_design_binary$variables$ObeseStatus)
# --- Example 1: Output on Ratio scale ---
simple_effects_ratio <- inteffects(
joint_model = joint_model_logit,
joint_var_name = "Race1_ObeseStatus",
factor1_name = "Race1",
factor2_name = "ObeseStatus",
factor1_levels = f1_levels,
factor2_levels = f2_levels,
level_separator = "_",
scale = "ratio"
)
print("--- Output on Ratio Scale ---")
print(simple_effects_ratio, n = 50)
# --- Example 2: Output on Log scale ---
simple_effects_log <- inteffects(
joint_model = joint_model_logit,
joint_var_name = "Race1_ObeseStatus",
factor1_name = "Race1",
factor2_name = "ObeseStatus",
factor1_levels = f1_levels,
factor2_levels = f2_levels,
level_separator = "_",
scale = "log"
)
print("--- Output on Log Scale ---")
print(simple_effects_log, n = 50)
}
#> [1] "--- Output on Ratio Scale ---"
#> # A tibble: 13 × 6
#> Comparison Estimate SE CI.low CI.upp `p-value`
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 ObeseStatus(Obese vs Not Obese): Race… 1.4 0.1 1.21 1.61 4.88e- 6
#> 2 ObeseStatus(Obese vs Not Obese): Race… 1.2 0.14 0.95 1.52 1.30e- 1
#> 3 ObeseStatus(Obese vs Not Obese): Race… 1.66 0.24 1.25 2.2 4.01e- 4
#> 4 ObeseStatus(Obese vs Not Obese): Race… 1.65 0.2 1.3 2.1 4.15e- 5
#> 5 ObeseStatus(Obese vs Not Obese): Race… 1.09 0.27 0.68 1.77 7.15e- 1
#> 6 Race1(Black vs White): ObeseStatus(No… 2.11 0.21 1.73 2.58 1.42e-13
#> 7 Race1(Hispanic vs White): ObeseStatus… 0.99 0.12 0.77 1.27 9.37e- 1
#> 8 Race1(Mexican vs White): ObeseStatus(… 1.17 0.12 0.95 1.43 1.37e- 1
#> 9 Race1(Other vs White): ObeseStatus(No… 1.05 0.1 0.87 1.28 6.00e- 1
#> 10 Race1(Black vs White): ObeseStatus(Ob… 1.81 0.23 1.41 2.33 3.75e- 6
#> 11 Race1(Hispanic vs White): ObeseStatus… 1.18 0.15 0.92 1.51 1.96e- 1
#> 12 Race1(Mexican vs White): ObeseStatus(… 1.38 0.2 1.03 1.84 2.96e- 2
#> 13 Race1(Other vs White): ObeseStatus(Ob… 0.82 0.19 0.52 1.31 4.14e- 1
#> [1] "--- Output on Log Scale ---"
#> # A tibble: 13 × 6
#> Comparison Estimate SE CI.low CI.upp `p-value`
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 ObeseStatus(Obese vs Not Obese): Ra… 0.335 0.0732 0.191 0.478 4.88e- 6
#> 2 ObeseStatus(Obese vs Not Obese): Ra… 0.182 0.120 -0.0538 0.418 1.30e- 1
#> 3 ObeseStatus(Obese vs Not Obese): Ra… 0.508 0.144 0.227 0.789 4.01e- 4
#> 4 ObeseStatus(Obese vs Not Obese): Ra… 0.500 0.122 0.261 0.740 4.15e- 5
#> 5 ObeseStatus(Obese vs Not Obese): Ra… 0.0896 0.246 -0.392 0.571 7.15e- 1
#> 6 Race1(Black vs White): ObeseStatus(… 0.748 0.101 0.550 0.946 1.42e-13
#> 7 Race1(Hispanic vs White): ObeseStat… -0.00992 0.125 -0.255 0.235 9.37e- 1
#> 8 Race1(Mexican vs White): ObeseStatu… 0.154 0.104 -0.0493 0.358 1.37e- 1
#> 9 Race1(Other vs White): ObeseStatus(… 0.0516 0.0983 -0.141 0.244 6.00e- 1
#> 10 Race1(Black vs White): ObeseStatus(… 0.595 0.129 0.343 0.848 3.75e- 6
#> 11 Race1(Hispanic vs White): ObeseStat… 0.164 0.127 -0.0845 0.412 1.96e- 1
#> 12 Race1(Mexican vs White): ObeseStatu… 0.320 0.147 0.0317 0.608 2.96e- 2
#> 13 Race1(Other vs White): ObeseStatus(… -0.193 0.237 -0.657 0.270 4.14e- 1
# }