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

R ggplot2:如何在分面散点图中为指定无关联点绘制连接线

解决方法

你之前添加geom_line(aes(x = stat, group=group))不符合预期的核心原因是:你设置的分组变量对应诊断等级,会跨多个test分面,ggplot会默认跨分面连接数据,同时会将三个stat的点全部串联,不符合你仅需要从患病率分别连接两个后验概率的需求。

正确实现方式为单独构造连接线专用的辅助数据集,仅保留需要连接的点对,再传入geom_line即可,完整可运行代码如下:

# 先加载需要的包
library(tidyverse)

# 载入你提供的数据集
probpostest <- structure(list(prev = c(15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 
15, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, 5, 5, 5, 5, 
5, 5), group = c("proven", "proven", "proven", "proven_likely", 
"proven_likely", "proven_likely", "proven_likely_possible", "proven_likely_possible", 
"proven_likely_possible", "proven", "proven", "proven", "proven_likely", 
"proven_likely", "proven_likely", "proven_likely_possible", "proven_likely_possible", 
"proven_likely_possible", "proven", "proven", "proven", "proven_likely", 
"proven_likely", "proven_likely", "proven_likely_possible", "proven_likely_possible", 
"proven_likely_possible", "proven", "proven", "proven", "proven", 
"proven", "proven", "proven", "proven", "proven", "proven", "proven", 
"proven", "proven", "proven", "proven", "proven", "proven", "proven"
), test = c("T2Candida", "T2Candida", "T2Candida", "T2Candida", 
"T2Candida", "T2Candida", "T2Candida", "T2Candida", "T2Candida", 
"Hemocultivo", "Hemocultivo", "Hemocultivo", "Hemocultivo", "Hemocultivo", 
"Hemocultivo", "Hemocultivo", "Hemocultivo", "Hemocultivo", "T2Candida + Hemocultivo", 
"T2Candida + Hemocultivo", "T2Candida + Hemocultivo", "T2Candida + Hemocultivo", 
"T2Candida + Hemocultivo", "T2Candida + Hemocultivo", "T2Candida + Hemocultivo", 
"T2Candida + Hemocultivo", "T2Candida + Hemocultivo", "T2Candida", 
"T2Candida", "T2Candida", "Hemocultivo", "Hemocultivo", "Hemocultivo", 
"T2Candida + Hemocultivo", "T2Candida + Hemocultivo", "T2Candida + Hemocultivo", 
"T2Candida", "T2Candida", "T2Candida", "Hemocultivo", "Hemocultivo", 
"Hemocultivo", "T2Candida + Hemocultivo", "T2Candida + Hemocultivo", 
"T2Candida + Hemocultivo"), stat = c("prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo", "prevalencia", "probpostestpositivo", 
"probpostestnegativo"), estimator = c(0.158, 0.635718612096565, 
0.0361721611721612, 0.404, 0.637998056365403, 0.351610095735422, 
0.561, 0.908822796377835, 0.472165444270771, 0.158, 1, 0.101195559350982, 
0.404, 1, 0.351610095735422, 0.561, 1, 0.534908358936328, 0.158, 
NA, 0.0184192119375146, 0.404, NA, 0.321802457897132, 0.561, 
NA, 0.472165444270771, 0.1, 0.508196721311476, 0.0217391304347826, 
0.1, 1, 0.0625, 0.1, NA, 0.010989010989011, 0.05, 0.328621908127209, 
0.0104166666666667, 0.05, 1, 0.0306122448979592, 0.05, NA, 0.00523560209424084
), lower = c("7.5", NA, NA, "27.6", NA, NA, "42.4", NA, NA, "7.5", 
NA, NA, "27.6", NA, NA, "42.4", NA, NA, "7.5", NA, NA, "27.6", 
NA, NA, "42.4", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA), upper = c("27.9", NA, NA, "54.2", 
NA, NA, "69.3", NA, NA, "27.9", NA, NA, "54.2", NA, NA, "69.3", 
NA, NA, "27.9", NA, NA, "54.2", NA, NA, "69.3", NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
)), row.names = c(NA, -45L), class = c("tbl_df", "tbl", "data.frame"
))

# 处理主绘图数据
plot_data <- probpostest %>%
  filter(prev==15) %>% 
  mutate(
    stat=replace(stat,stat=="prevalencia","Prevalencia"),
    stat=replace(stat,stat=="probpostestpositivo","Probabilidad\nPostest\nPositivo"),
    stat=replace(stat,stat=="probpostestnegativo","Probabilidad\nPostest\nNegativo"),
    group=replace(group,group=="proven","Confirmada"),
    group=replace(group,group=="proven_likely","Confirmada o\nprobable"),
    group=replace(group,group=="proven_likely_possible","Confirmada,\nprobable o\nposible"),
    # 提前计算y值,方便后续构造连接线数据
    y_val = if_else(is.na(estimator*100), 100, estimator*100)
  ) %>% 
  mutate(across(stat, factor, levels=c("Prevalencia","Probabilidad\nPostest\nPositivo","Probabilidad\nPostest\nNegativo")),
         across(c(lower,upper), as.numeric),
         lower=lower/100,
         upper=upper/100)

# 构造连接线辅助数据:每个分面内仅保留 患病率→阳性后验、患病率→阴性后验 两组连线
line_data <- plot_data %>%
  # 过滤掉estimator为NA的点,不需要连接NC标签的位置
  filter(!is.na(estimator)) %>%
  group_by(group, test) %>%
  # 每组生成两条连线
  reframe(
    line1 = list(tibble(
      stat = c("Prevalencia", "Probabilidad\nPostest\nPositivo"),
      y_val = c(y_val[stat=="Prevalencia"], y_val[stat=="Probabilidad\nPostest\nPositivo"])
    )),
    line2 = list(tibble(
      stat = c("Prevalencia", "Probabilidad\nPostest\nNegativo"),
      y_val = c(y_val[stat=="Prevalencia"], y_val[stat=="Probabilidad\nPostest\nNegativo"])
    ))
  ) %>%
  unnest(cols = c(line1, line2), names_sep = "_") %>%
  # 整理成长格式,给每条连线分配唯一id
  pivot_longer(cols = -c(group, test), names_to = c("line_id", ".value"), names_sep = "_") %>%
  filter(!is.na(y_val))

# 绘图
ggplot(plot_data, aes(x=stat, y=y_val, ymin=lower, ymax=upper, color=stat)) +
  # 先加连接线,放在点图层下方避免遮挡
  geom_line(data = line_data, aes(x = stat, y = y_val, group = line_id), 
            color = "gray50", linewidth = 0.8, inherit.aes = FALSE) +
  geom_point(size = 2) + 
  geom_text(aes(label=if_else(is.na(estimator),
                              "NC",
                              paste0(sprintf("%2.2f",estimator*100),"%")),
                vjust=if_else(is.infinite(estimator),
                              1,
                              0.5),
                hjust=-0.25),
            show.legend = FALSE,
            size=4) + 
  labs(x=NULL,y=NULL,title = "Figura 5. Probabilidades pre-test y post-test.",
       caption="Prevalencia: probabilidad pre-test.\n\nProbabilidad pos-test positivo y negativo: probabilidad de tener candidiasis invasiva después de obtener un resultado positivo o negativo, respectivamente.\n\nNC: no calculable.")+
  facet_grid(group ~ test,
             scales = "free_y",
             switch = "y"
  ) +
  theme_minimal()+
  theme(plot.title = element_text(hjust = 0.5),
        plot.caption = element_text(hjust = 0),
        legend.position = "none",
        strip.text = element_text(face="bold")) +
  scale_y_continuous(position = "right") +
  scale_color_brewer(palette = "Set1")

如果需要调整连接线的颜色、粗细,直接修改geom_line里的color、linewidth参数即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 01:36:05