You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言forestplot包group_by操作时出现逻辑值缺失错误求助

解决forestplot分组绘制亚组森林图的错误问题

错误原因分析

报错核心是分组绘图时txt_gp的样式处理逻辑错误,同时group_by()结合fp_decorate_graph时,标签结构不匹配导致判断逻辑出现NA值。具体来说:

  • fp_set_style中对txt_gp使用lapply包装gpar(fill = x)是错误操作,fpTxtGp返回特定结构的列表,不能直接用该方式修改填充色
  • 原代码未在标签中明确区分亚组,导致fp_decorate_graph无法正确识别标签位置,触发NA值判断错误

修正后的完整代码

library(forestplot)
library(dplyr)

# 1. 定义原始数据框
AAA_smoker_HR_2 <- tibble::tibble(mean  = c(1.23, 0.90, 0.86),
                                  lower = c(0.87, 0.87, 0.81),
                                  upper = c(1.73, 0.94, 0.92),
                                  var = c("In-Hospital Mortality",
                                          "Length of Hospital Stay",
                                          "Length of ITU Stay"),
                                  HR = c("1.23 (0.87-1.73)", "0.90 (0.87-0.94)", "0.86 (0.81-0.92)"))

OSR_smoker_HR_2 <- tibble::tibble(mean  = c(1.18, 1.00, 0.96),
                                  lower = c(0.87, 0.97, 0.91),
                                  upper = c(1.60, 1.04, 1.01),
                                  var = c("In-Hospital Mortality",
                                          "Length of Hospital Stay",
                                          "Length of ITU Stay"),
                                  HR = c("1.18 (0.87-1.60)", "1.00 (0.97-1.04)", "0.96 (0.91-1.01)"))

EVAR_smoker_HR_2 <- tibble::tibble(mean  = c(1.22, 0.98, 0.92),
                                   lower = c(0.82, 0.91, 0.85),
                                   upper = c(1.82, 1.04, 0.99),
                                   var = c("In-Hospital Mortality",
                                           "Length of Hospital Stay",
                                           "Length of ITU Stay"),
                                   HR = c("1.22 (0.82-1.82)", "0.98 (0.91-1.04)", "0.92 (0.85-0.99)"))

# 2. 合并并整理数据,添加分组标题行
AAA_J_smoker_HR <- bind_rows(lst(AAA_smoker_HR_2, OSR_smoker_HR_2, EVAR_smoker_HR_2), .id = 'study') %>%
  mutate(study = case_when(
    study == "AAA_smoker_HR_2" ~ "All",
    study == "OSR_smoker_HR_2" ~ "OSR",
    study == "EVAR_smoker_HR_2" ~ "EVAR"
  )) %>%
  group_by(study) %>%
  # 为每个分组添加标题行(空值占位)
  group_modify(~bind_rows(tibble(mean = NA, lower = NA, upper = NA, var = .y$study, HR = ""), .x)) %>%
  ungroup()

# 3. 定义绘图样式参数
ci_functions <- c(fpDrawDiamondCI, fpDrawNormalCI, fpDrawCircleCI)
box_colors <- c("black", "blue", "darkred")

# 4. 绘制分组森林图
AAA_J_smoker_HR %>%
  forestplot(
    labeltext = c(var, HR),
    # 按分组循环分配CI绘图函数
    fn.ci_norm = rep(ci_functions, each = 4), # 每个分组含1个标题行+3个结局行
    zero = 1,
    clip = c(0.0, 3.0),
    boxsize = 0.18,
    vertices = TRUE,
    ci.vertices.height = 0.05,
    lineheight = "lines",
    xlab = "Hazard Ratio (HR)",
    xticks = c(0.5, 1.0, 1.5, 2.0, 3.0),
    # 为分组设置对应框颜色
    col = fpColors(box = rep(box_colors, each = 4), line = "black")
  ) %>%
  fp_add_lines() %>%
  fp_set_style(
    hrz_lines = "#999999",
    txt_gp = fpTxtGp(
      ticks = gpar(cex = 0.75),
      label = gpar(cex = 0.9),
      xlab = gpar(cex = 0.9),
      # 分组标题加粗突出
      title = gpar(cex = 1, fontface = "bold")
    )
  ) %>%
  fp_add_header(
    var = c("", "Variable"),
    HR = c("", "HR (95% CI)")
  ) %>%
  # 跳过标题行的CI绘制(标题行无有效数据)
  fp_omit_lines(mean.is.na = TRUE)

关键修改说明

  1. 添加分组标题行:通过group_modify为每个亚组添加独立标题行,既清晰区分亚组,又避免标签结构不匹配问题
  2. 修正CI函数与颜色的循环逻辑:用rep(..., each = 4)确保每个亚组的标题+结局行对应正确的绘图函数和颜色
  3. 移除错误的txt_gp处理:删除原代码中对fpTxtGp的lapply包装,改用fpColors统一设置框颜色,规避样式处理时的NA值问题
  4. 替换fp_decorate_graph为fp_omit_lines:用fp_omit_lines跳过无数据的标题行CI绘制,解决分组绘图时的标签判断错误

内容的提问来源于stack exchange,提问作者Kitty Wong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 05:08:14