## ----setup-------------------------------------------------------------------- #| include: false library(forrest) ## ----basic-------------------------------------------------------------------- dat <- data.frame( predictor = c("Age (per 10 y)", "Female sex", "BMI (per 5 kg/m\u00b2)", "Current smoker", "Physically active"), estimate = c( 0.18, -0.42, 0.11, -0.31, 0.24), lower = c( 0.05, -0.61, -0.04, -0.52, 0.08), upper = c( 0.31, -0.23, 0.26, -0.10, 0.40) ) forrest( dat, estimate = "estimate", lower = "lower", upper = "upper", label = "predictor", xlab = "Regression coefficient (95% CI)" ) ## ----section------------------------------------------------------------------ #| fig-height: 5 sub_dat <- data.frame( subgroup = c("Sex", "Sex", "Age group", "Age group", "Age group"), label = c("Female", "Male", "30\u201349 years", "50\u201369 years", "70+ years"), estimate = c(-0.38, 0.12, 0.22, -0.15, -0.41), lower = c(-0.58, -0.08, 0.02, -0.38, -0.66), upper = c(-0.18, 0.32, 0.42, 0.08, -0.16) ) forrest( sub_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "label", section = "subgroup", xlab = "Regression coefficient (95% CI)", header = "Subgroup" ) ## ----subsection--------------------------------------------------------------- #| fig-height: 7 nested_dat <- data.frame( domain = c( "Physical environment", "Physical environment", "Physical environment", "Physical environment", "Physical environment", "Social environment", "Social environment", "Social environment", "Social environment" ), type = c( "Air quality", "Air quality", "Urban form", "Urban form", "Urban form", "Support", "Support", "Deprivation", "Deprivation" ), predictor = c( "PM2.5 (per 10 \u03bcg/m\u00b3)", "NO2 (per 10 ppb)", "Green space (%)", "Walkability", "Noise (per 10 dB)", "Social cohesion", "Social isolation", "Area deprivation", "Employment rate" ), estimate = c(-0.18, 0.12, -0.22, 0.15, -0.08, -0.11, 0.09, 0.05, -0.03), lower = c(-0.38, -0.08, -0.42, -0.05, -0.28, -0.31, -0.09, -0.12, -0.20), upper = c( 0.02, 0.32, -0.02, 0.35, 0.12, 0.09, 0.27, 0.22, 0.14) ) forrest( nested_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "predictor", section = "domain", subsection = "type", xlab = "Mean difference in SBP (mmHg, 95% CI)" ) ## ----summary------------------------------------------------------------------ sex_dat <- data.frame( label = c("Female", "Male", "Overall"), estimate = c(-0.42, -0.29, -0.36), lower = c(-0.61, -0.48, -0.50), upper = c(-0.23, -0.10, -0.22), is_sum = c(FALSE, FALSE, TRUE) ) forrest( sex_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "label", is_summary = "is_sum", xlab = "Regression coefficient (95% CI)", title = "Association of female sex with SBP by subgroup" ) ## ----grouped------------------------------------------------------------------ #| fig-height: 5 grp_dat <- data.frame( predictor = rep( c("Air pollution (PM2.5)", "Noise exposure", "Green space access", "Walkability index", "Food environment"), 2 ), domain = rep(c("Physical environment", "Social environment"), each = 5), estimate = c(-0.18, 0.12, -0.22, 0.15, -0.08, 0.05, -0.03, 0.09, -0.11, 0.14), lower = c(-0.38, -0.08, -0.42, -0.05, -0.28, -0.12, -0.20, -0.09, -0.31, -0.04), upper = c( 0.02, 0.32, -0.02, 0.35, 0.12, 0.22, 0.14, 0.27, 0.09, 0.32) ) forrest( grp_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "predictor", group = "domain", xlab = "Mean difference in SBP (mmHg, 95% CI)" ) ## ----dodge-------------------------------------------------------------------- #| fig-height: 4 #| fig-width: 9 dodge_dat <- data.frame( exposure = rep( c("PM2.5 (per 10 \u03bcg/m\u00b3)", "NO2 (per 10 ppb)", "Noise (per 10 dB)", "Green space (%)", "Walkability"), each = 2 ), period = rep(c("Childhood", "Adulthood"), 5), estimate = c( 0.14, -0.05, 0.08, 0.12, -0.19, -0.06, 0.11, -0.03, 0.07, 0.10 ), lower = c( -0.10, -0.26, -0.09, -0.08, -0.40, -0.25, -0.05, -0.12, -0.14, -0.09 ), upper = c( 0.38, 0.16, 0.25, 0.32, 0.02, 0.13, 0.27, 0.06, 0.28, 0.29 ) ) forrest( dodge_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "exposure", group = "period", dodge = TRUE, header = "Environmental exposure", ref_line = 0, xlab = "Mean difference in SBP (mmHg, 95% CI)" ) ## ----dodge-cols--------------------------------------------------------------- #| fig-height: 4 #| fig-width: 11 # Add per-condition formatted text columns to the long-format data dodge_dat$est_ci <- sprintf("%.2f (%.2f, %.2f)", dodge_dat$estimate, dodge_dat$lower, dodge_dat$upper) dodge_dat$text_child <- ifelse( dodge_dat$period == "Childhood", dodge_dat$est_ci, "" ) dodge_dat$text_adult <- ifelse( dodge_dat$period == "Adulthood", dodge_dat$est_ci, "" ) forrest( dodge_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "exposure", group = "period", dodge = TRUE, cols_by_group = TRUE, cols = c("Childhood (95% CI)" = "text_child", "Adulthood (95% CI)" = "text_adult"), widths = c(2.8, 3.5, 2.2, 2.2), header = "Environmental exposure", ref_line = 0, xlab = "Mean difference in SBP (mmHg, 95% CI)" ) ## ----shape-------------------------------------------------------------------- #| fig-height: 5 #| fig-width: 9 shape_dat <- data.frame( exposure = rep( c("PM2.5 (per 10 \u03bcg/m\u00b3)", "NO2 (per 10 ppb)", "Noise (per 10 dB)", "Green space (%)", "Walkability"), each = 4 ), period = rep(rep(c("Childhood", "Adulthood"), each = 2), 5), sex = rep(c("Female", "Male"), 10), estimate = c( 0.22, -0.08, -0.10, 0.18, 0.11, 0.05, 0.00, 0.14, -0.31, 0.06, -0.09, -0.02, 0.08, 0.12, -0.04, 0.03, 0.17, -0.06, 0.22, 0.01 ), lower = c( -0.20, -0.38, -0.28, -0.14, -0.12, -0.22, -0.22, -0.14, -0.56, -0.24, -0.38, -0.30, -0.18, -0.14, -0.22, -0.15, -0.09, -0.38, -0.04, -0.27 ), upper = c( 0.64, 0.22, 0.08, 0.50, 0.34, 0.32, 0.22, 0.42, -0.06, 0.36, 0.20, 0.26, 0.34, 0.38, 0.14, 0.21, 0.43, 0.26, 0.48, 0.29 ) ) forrest( shape_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "exposure", group = "period", shape = "sex", dodge = TRUE, ref_line = 0, xlab = "Mean difference in SBP (mmHg, 95% CI)" ) ## ----text-cols---------------------------------------------------------------- #| fig-height: 4.5 #| fig-width: 10 tc_dat <- data.frame( predictor = c("Age (per 10 y)", "Female sex", "BMI (per 5 kg/m\u00b2)", "Current smoker", "Physically active"), estimate = c( 0.18, -0.42, 0.11, -0.31, 0.24), lower = c( 0.05, -0.61, -0.04, -0.52, 0.08), upper = c( 0.31, -0.23, 0.26, -0.10, 0.40), coef_ci = c( " 0.18 ( 0.05, 0.31)", "-0.42 (-0.61, -0.23)", " 0.11 (-0.04, 0.26)", "-0.31 (-0.52, -0.10)", " 0.24 ( 0.08, 0.40)" ), pval = c("0.006", "<0.001", "0.148", "0.003", "0.009") ) forrest( tc_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "predictor", header = "Predictor", cols = c("Coef (95% CI)" = "coef_ci", "P-value" = "pval"), widths = c(2.8, 4, 2.5, 1.2), xlab = "Regression coefficient (95% CI)" ) ## ----section-cols------------------------------------------------------------- #| fig-height: 5 #| fig-width: 11 sc_dat <- data.frame( subgroup = c("Sex", "Sex", "Age group", "Age group", "Age group"), label = c("Female", "Male", "30\u201349 y", "50\u201369 y", "70+ y"), estimate = c(-0.38, 0.12, 0.22, -0.15, -0.41), lower = c(-0.58, -0.08, 0.02, -0.38, -0.66), upper = c(-0.18, 0.32, 0.42, 0.08, -0.16), coef_ci = c( "-0.38 (-0.58, -0.18)", " 0.12 (-0.08, 0.32)", " 0.22 ( 0.02, 0.42)", "-0.15 (-0.38, 0.08)", "-0.41 (-0.66, -0.16)" ), # Constant within each section — section header will show this value k_text = c("k = 2", "k = 2", "k = 3", "k = 3", "k = 3") ) forrest( sc_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "label", section = "subgroup", section_cols = c("k" = "k_text"), header = "Subgroup", cols = c("Coef (95% CI)" = "coef_ci", "k" = "k_text"), widths = c(2.5, 4, 2.5, 1.2), xlab = "Regression coefficient (95% CI)" ) ## ----stripe------------------------------------------------------------------- #| fig-height: 6 stripe_dat <- data.frame( label = c( "Age (per 10 y)", "Female sex", "BMI (per 5 kg/m\u00b2)", "Current smoker", "Physically active", "Alcohol intake", "Sleep duration", "Depressive symptoms" ), estimate = c( 0.42, -0.18, 0.31, -0.07, 0.25, -0.12, 0.19, -0.34), lower = c( 0.22, -0.38, 0.12, -0.24, 0.06, -0.30, 0.01, -0.52), upper = c( 0.62, 0.02, 0.50, 0.10, 0.44, 0.06, 0.37, -0.16) ) forrest( stripe_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "label", stripe = TRUE, xlab = "Regression coefficient (95% CI)" ) ## ----themes-minimal----------------------------------------------------------- #| fig-height: 3.5 theme_dat <- data.frame( predictor = c("Age (per 10 y)", "Female sex", "BMI (per 5 kg/m\u00b2)"), estimate = c( 0.18, -0.42, 0.11), lower = c( 0.05, -0.61, -0.04), upper = c( 0.31, -0.23, 0.26) ) # "minimal" theme — lighter gridlines and softer reference line forrest( theme_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "predictor", theme = "minimal", title = 'theme = "minimal"', xlab = "Coefficient (95% CI)" ) ## ----themes-classic----------------------------------------------------------- #| fig-height: 3.5 # "classic" theme — dotted gridlines and solid black reference line forrest( theme_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "predictor", theme = "classic", title = 'theme = "classic"', xlab = "Coefficient (95% CI)" ) ## ----themes-custom------------------------------------------------------------ #| fig-height: 3.5 # Custom theme — override individual style keys forrest( theme_dat, estimate = "estimate", lower = "lower", upper = "upper", label = "predictor", theme = list(ref_col = "#e63946", ref_lty = 1L, grid_col = "#eeeeee"), title = "Custom theme (red reference line)", xlab = "Coefficient (95% CI)" ) ## ----save--------------------------------------------------------------------- #| eval: false # save_forrest( # file = "my_forest_plot.pdf", # plot = function() { # forrest( # dat, # estimate = "estimate", # lower = "lower", # upper = "upper", # label = "predictor", # xlab = "Regression coefficient (95% CI)" # ) # }, # width = 8, # height = 5 # )