Source
为亚组森林图模拟的 9 个效应估计:全队列 1 行,年龄和性别各 2 行,BMI 4 行。CSV 只保存分析结果;分组标题与缩进由绘图代码根据 group 生成。
Use cases
- 绘制带 Overall、Age、Sex 和 BMI 层级的亚组森林图
- 演示组间交互作用 p 值的展示
- 在绘图阶段自动插入组标题并生成缩进
Simulated overall and subgroup hazard ratios for incident type 2 diabetes.
One row represents one overall or subgroup estimate.
Tessera · 收录于 2026-09-02
| group | level | n | n_events | HR | CI_lower | CI_upper | p_value | p_interaction | HR_label |
|---|---|---|---|---|---|---|---|---|---|
| Overall | Overall | 440,045 | 40,199 | 1.42 | 1.35 | 1.49 | 2.40e-48 | NA | 1.42 (1.35, 1.49) |
| Age | <60 years | 182,316 | 11,254 | 1.31 | 1.21 | 1.42 | 4.52e-11 | 0.038 | 1.31 (1.21, 1.42) |
| Age | >=60 years | 257,729 | 28,945 | 1.5 | 1.41 | 1.59 | 4.31e-39 | 0.038 | 1.50 (1.41, 1.59) |
| Sex | Female | 238,119 | 18,772 | 1.37 | 1.28 | 1.46 | 2.06e-20 | 0.214 | 1.37 (1.28, 1.46) |
| Sex | Male | 201,926 | 21,427 | 1.47 | 1.38 | 1.57 | 1.72e-31 | 0.214 | 1.47 (1.38, 1.57) |
| BMI | Underweight | 18,421 | 2,184 | 1.16 | 0.994 | 1.35 | 0.0603 | 0.006 | 1.16 (0.99, 1.35) |
| # | 变量 | 类型 | 缺失 | 统计 |
|---|---|---|---|---|
| 1 | groupSubgroup variable; Overall identifies the estimate for the full cohort. | 字符型 | — | 不同值 4BMI · Age · Sex · Overall |
| 2 | levelPopulation level represented by the estimate. | 字符型 | — | 不同值 9Overall · <60 years · >=60 years · Female · Male · Underweight · Normal weight · Overweight |
| 3 | nParticipants in the analytic sample. | 整数 | — | min 18,421q1 —中位 182,316均值 195,576q3 —max 440,045 |
| 4 | n_eventsIncident type 2 diabetes cases observed during follow-up. | 整数 | — | min 2,184q1 —中位 15,086均值 17,866q3 —max 40,199 |
| 5 | HRkeySimulated hazard ratio for incident type 2 diabetes. | 双精度 | — | min 1q1 —中位 1.39均值 1.38q3 —max 1.82 |
| 6 | CI_lowerLower bound of the 95% confidence interval. | 双精度 | — | min 0.903q1 —中位 1.31均值 1.28q3 —max 1.7 |
| 7 | CI_upperUpper bound of the 95% confidence interval. | 双精度 | — | min 1.11q1 —中位 1.48均值 1.49q3 —max 1.95 |
| 8 | p_valueTwo-sided Wald p value for the effect estimate. | 双精度 | — | min 1.3e-65q1 —中位 7.8e-25均值 0.118q3 —max 1 |
| 9 | p_interactionInteraction p value shared by levels of the same subgroup variable. | 双精度 | 1 | min 0.006q1 —中位 0.022均值 0.066q3 —max 0.214 |
| 10 | HR_labelPreformatted hazard ratio and 95% confidence interval. | 字符型 | — | 不同值 91.42 (1.35, 1.49) · 1.31 (1.21, 1.42) · 1.50 (1.41, 1.59) · 1.37 (1.28, 1.46) · 1.47 (1.38, 1.57) · 1.16 (0.99, 1.35) · 1.00 (0.90, 1.11) · 1.39 (1.31, 1.48) |
library(readr)
forest_subgroups <- read_csv(
"https://assets.evanzhou.org/tessera/csv/forest_subgroups.csv",
col_types = cols(
group = col_character(),
level = col_character(),
n = col_integer(),
n_events = col_integer(),
HR = col_double(),
CI_lower = col_double(),
CI_upper = col_double(),
p_value = col_double(),
p_interaction = col_double(),
HR_label = col_character()
)
)https://assets.evanzhou.org/tessera/csv/forest_subgroups.csv为亚组森林图模拟的 9 个效应估计:全队列 1 行,年龄和性别各 2 行,BMI 4 行。CSV 只保存分析结果;分组标题与缩进由绘图代码根据 group 生成。
# Generate the subgroup toy data used by the forest figure recipes.
script_dir <- local({
arg <- grep("^--file=", commandArgs(trailingOnly = FALSE), value = TRUE)
path <- if (length(arg)) sub("^--file=", "", arg[[1L]]) else sys.frame(1)$ofile
dirname(normalizePath(path, mustWork = TRUE))
})
out_csv <- file.path(script_dir, "..", "csv", "forest_subgroups.csv")
dir.create(dirname(out_csv), recursive = TRUE, showWarnings = FALSE)
forest_subgroups <- data.frame(
group = c("Overall", "Age", "Age", "Sex", "Sex", "BMI", "BMI", "BMI", "BMI"),
level = c(
"Overall", "<60 years", ">=60 years", "Female", "Male",
"Underweight", "Normal weight", "Overweight", "Obese"
),
n = c(440045L, 182316L, 257729L, 238119L, 201926L, 18421L, 156804L, 168735L, 96085L),
n_events = c(40199L, 11254L, 28945L, 18772L, 21427L, 2184L, 10591L, 15086L, 12338L),
HR = c(1.42, 1.31, 1.50, 1.37, 1.47, 1.16, 1.00, 1.39, 1.82),
se = c(0.024, 0.041, 0.031, 0.034, 0.033, 0.079, 0.052, 0.032, 0.035),
p_interaction = c(NA, 0.038, 0.038, 0.214, 0.214, 0.006, 0.006, 0.006, 0.006)
)
log_hr <- log(forest_subgroups$HR)
forest_subgroups$CI_lower <- exp(log_hr - 1.96 * forest_subgroups$se)
forest_subgroups$CI_upper <- exp(log_hr + 1.96 * forest_subgroups$se)
forest_subgroups$p_value <- 2 * pnorm(-abs(log_hr / forest_subgroups$se))
forest_subgroups$se <- NULL
forest_subgroups$HR <- round(forest_subgroups$HR, 4)
forest_subgroups$CI_lower <- round(forest_subgroups$CI_lower, 4)
forest_subgroups$CI_upper <- round(forest_subgroups$CI_upper, 4)
forest_subgroups$HR_label <- sprintf(
"%.2f (%.2f, %.2f)",
forest_subgroups$HR, forest_subgroups$CI_lower, forest_subgroups$CI_upper
)
forest_subgroups <- forest_subgroups[, c(
"group", "level", "n", "n_events", "HR", "CI_lower", "CI_upper",
"p_value", "p_interaction", "HR_label"
)]
write.csv(forest_subgroups, out_csv, row.names = FALSE)表中统计由 scripts/profile_dataset.py 于 2026-09-02 数出。