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

如何用ggplot2调整森林图OR标签至条形上方而非中间

调整ggplot2森林图中OR标签位置至条形上方

需要修改ggplot2代码,将森林图里的OR(优势比)标签从条形中间移到条形上方,以下是原代码、当前效果及修改后的解决方案:

原代码

library(tidyverse)
library(ggplot2)

# Create a data frame with your odds ratios and confidence intervals
odds_ratios <- c(1.290, 1.217, 1.231, 1.242)
ci_lower <- c(1.107, 1.038, 1.019, 1.028)
ci_upper <- c(1.504, 1.427, 1.486, 1.500)
or <- c(1.29, 1.22, 1.23, 1.24)
ci <- c("1.11 to 1.50", " 1.04 to 1.43", "1.02 to 1.49", "1.24 to 1.50")

Model <- c("Unadjusted (AUC=53.1%)", "Adjusted for family factors (AUC=63.1%)", 
           "Adjusted for family and self-functioning factors (AUC=85.0%)", 
           "Adjusted for family, self-functioning, and socio-demographic factors (AUC=85.2%)")

# Create a data frame
data <- data.frame(
  Model = Model,
  Odds_Ratio = odds_ratios,
  CI_lower = ci_lower,
  CI_upper = ci_upper,
  or <- or,
  ci <- ci

)

# Define the desired order of levels
desired_order <- c("Unadjusted (AUC=53.1%)", "Adjusted for family factors (AUC=63.1%)", 
                   "Adjusted for family and self-functioning factors (AUC=85.0%)", 
                   "Adjusted for family, self-functioning, and socio-demographic factors (AUC=85.2%)")

# Reorder the data frame rows based on the desired order
data <- data %>%
  mutate(Model = factor(Model, levels = desired_order)) %>%
  arrange(Model)

# Add a row number column
data$row_num <- 1:nrow(data)

# Define custom breaks and labels for the x-axis
custom_breaks <- c(0.5, 1, 1.2, 1.5)
custom_labels <- c(" ", "Just as likely", "1.2x as likely", "1.5x as likely")

# Add significance column
data$Significance <- ifelse(data$CI_lower > 1 | data$CI_upper < 1, "Significant", "Not Significant")

# Wrap long labels
data$Model <- factor(str_wrap(data$Model, width = 30),
                     levels = str_wrap(desired_order, width = 30))

# Create the forest plot with customized labels
ggplot(data, aes(x = Odds_Ratio, y = fct_rev(Model))) +
  geom_vline(xintercept = 1, linetype = "dashed", color = "gray") +
  geom_point(aes(x = Odds_Ratio, color = Significance), size = 3) +
  geom_errorbarh(aes(xmin = CI_lower, xmax = CI_upper), height = 0.3) +
  scale_x_continuous(breaks = custom_breaks, labels = custom_labels) +
  scale_color_manual(values = c("Significant" = "red", "Not Significant" = "black")) +
  theme_minimal() +
  labs(x = "Odds Ratio", y = " ") +
  ggtitle(paste("Odds Ratios for Family Affectedness of Individual Chronic Pain:", "\n", "Women vs. Men")) +
  theme(
    axis.title.y = element_blank(),
    axis.text = element_text(size = 10),
    panel.grid.major.y = element_line(color = "gray", linetype = "dashed"),
    legend.position = "none",
    plot.title = element_text(hjust = 0.5, lineheight = 1.2)
  )

当前效果

森林图效果截图

修改后的代码

library(tidyverse)
library(ggplot2)

# Create a data frame with your odds ratios and confidence intervals
odds_ratios <- c(1.290, 1.217, 1.231, 1.242)
ci_lower <- c(1.107, 1.038, 1.019, 1.028)
ci_upper <- c(1.504, 1.427, 1.486, 1.500)
or <- c(1.29, 1.22, 1.23, 1.24)
ci <- c("1.11 to 1.50", " 1.04 to 1.43", "1.02 to 1.49", "1.24 to 1.50")

Model <- c("Unadjusted (AUC=53.1%)", "Adjusted for family factors (AUC=63.1%)", 
           "Adjusted for family and self-functioning factors (AUC=85.0%)", 
           "Adjusted for family, self-functioning, and socio-demographic factors (AUC=85.2%)")

# 修正数据框列赋值错误:将<-改为=
data <- data.frame(
  Model = Model,
  Odds_Ratio = odds_ratios,
  CI_lower = ci_lower,
  CI_upper = ci_upper,
  or = or,
  ci = ci
)

# Define the desired order of levels
desired_order <- c("Unadjusted (AUC=53.1%)", "Adjusted for family factors (AUC=63.1%)", 
                   "Adjusted for family and self-functioning factors (AUC=85.0%)", 
                   "Adjusted for family, self-functioning, and socio-demographic factors (AUC=85.2%)")

# Reorder the data frame rows based on the desired order
data <- data %>%
  mutate(Model = factor(Model, levels = desired_order)) %>%
  arrange(Model)

# Add a row number column
data$row_num <- 1:nrow(data)

# Define custom breaks and labels for the x-axis
custom_breaks <- c(0.5, 1, 1.2, 1.5)
custom_labels <- c(" ", "Just as likely", "1.2x as likely", "1.5x as likely")

# Add significance column
data$Significance <- ifelse(data$CI_lower > 1 | data$CI_upper < 1, "Significant", "Not Significant")

# Wrap long labels
data$Model <- factor(str_wrap(data$Model, width = 30),
                     levels = str_wrap(desired_order, width = 30))

# Create the forest plot with OR labels above bars
ggplot(data, aes(x = Odds_Ratio, y = fct_rev(Model))) +
  geom_vline(xintercept = 1, linetype = "dashed", color = "gray") +
  geom_errorbarh(aes(xmin = CI_lower, xmax = CI_upper), height = 0.3) +
  geom_point(aes(x = Odds_Ratio, color = Significance), size = 3) +
  # 添加OR标签,通过y轴偏移将标签放在条形上方
  geom_text(aes(label = paste("OR =", or), y = as.numeric(fct_rev(Model)) + 0.2), 
            size = 3, hjust = 0.5) +
  scale_x_continuous(breaks = custom_breaks, labels = custom_labels) +
  scale_color_manual(values = c("Significant" = "red", "Not Significant" = "black")) +
  theme_minimal() +
  labs(x = "Odds Ratio", y = " ") +
  ggtitle(paste("Odds Ratios for Family Affectedness of Individual Chronic Pain:", "\n", "Women vs. Men")) +
  theme(
    axis.title.y = element_blank(),
    axis.text = element_text(size = 10),
    panel.grid.major.y = element_line(color = "gray", linetype = "dashed"),
    legend.position = "none",
    plot.title = element_text(hjust = 0.5, lineheight = 1.2)
  )

关键修改点

  • 修正了数据框中列的赋值错误:原代码使用<-会导致列名异常,改为=后才能正确调用or列
  • 添加geom_text()层,通过y = as.numeric(fct_rev(Model)) + 0.2设置垂直偏移量,将OR标签放置在每个模型对应的点/误差线的上方
  • 可以根据需要调整偏移数值(比如0.2)或vjust参数来微调标签位置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 14:42:05