在ggplot2中连接两个不同轴上的连续和离散数据

Connecting continuous and discrete data on two different axis in ggplot2

我得到的数据对于 200 个样本是连续的,然后是相同样本的不同结果但是是离散的(Pos、Neg 和 fail)。我以为我可以使用 ggpaired 和辅助轴之类的东西连接两组数据,但没有成功。我需要连续数据的箱线图,但对于离散数据,我可以接受连接到次轴上特定点或分组的数据。

相当基础,但它大致给出了我想要的,只是没有单独的轴:

ggpaired(samples, cond1="discreteresult", cond2="PCRresult", id="sample")

但最终得到这张图,其中所有内容都绘制在同一轴上:

ggpaired_data

我以为我可以使用辅助轴?但是我尝试的一切似乎并不能让我仍然连接这些点?我可以尝试其他任何套餐吗?我试着玩 ggalluvial 但也没有运气。非常感谢任何帮助!

示例数据:

sample  discreteresult  PCRresult 
OXPOS.001   Pos 35 
OXPOS.002   Pos 29
OXPOS.003   Pos 25 
OXPOS.004   Pos 28 
OXPOS.005   Pos 31 
OXPOS.006   Pos 25 
OXPOS.007   Pos 32 
OXPOS.008   Pos 26 
OXPOS.009   Pos 28 
OXPOS.010   Pos 29 
OXPOS.011   Pos 35 
OXPOS.012   Neg 32 
OXPOS.013   Neg 35 
OXPOS.014   Neg 26 
OXPOS.015   Neg 30 
OXPOS.016   Neg 30 
OXPOS.017   Fail    27 
OXPOS.018   Fail    41 
OXPOS.019   Fail    12 
OXPOS.020   Neg 22

如果我明白你想做什么,我有一个解决方案,但它有点复杂。首先,我们有您的数据:

dat <- tibble::tribble(
  ~sample, ~discreteresult, ~PCRresult, 
  "OXPOS.001","Pos", 35, 
  "OXPOS.002","Pos", 29,
  "OXPOS.003","Pos", 25, 
  "OXPOS.004","Pos", 28, 
  "OXPOS.005","Pos", 31, 
  "OXPOS.006","Pos", 25, 
  "OXPOS.007","Pos", 32, 
  "OXPOS.008","Pos", 26, 
  "OXPOS.009","Pos", 28, 
  "OXPOS.010","Pos", 29, 
  "OXPOS.011","Pos", 35, 
  "OXPOS.012","Neg", 32, 
  "OXPOS.013","Neg", 35, 
  "OXPOS.014","Neg", 26, 
  "OXPOS.015","Neg", 30, 
  "OXPOS.016","Neg", 30, 
  "OXPOS.017","Fail", 27, 
  "OXPOS.018","Fail", 41, 
  "OXPOS.019","Fail", 12, 
  "OXPOS.020","Neg", 22)

接下来,我们需要弄清楚三个点 - 正、负和失败在同一个 y-axis 上的位置。我让它们均匀分布(在下面的对象 x 中):

library(tidyr)
library(dplyr)
library(ggplot2)

rg <- range(dat$PCRresult)
x <- rg[1] + diff(rg)/4 * 1:3

然后,我们从中制作数据集并将其与原始数据合并:

vals <- tibble(
  discreteresult = c("Pos", "Neg", "Fail"), 
  discreteval = x)
dat <- left_join(dat, vals)

接下来,我们将这个新数据 re-shape 设为长格式,以便变量 var 标识结果是离散的还是 PCR 的。

dat2 <- dat %>% 
  pivot_longer(cols=c("PCRresult", "discreteval"), 
               names_to="var", 
               values_to = "vals") %>% 
  mutate(var = factor(var, 
                      levels=c("PCRresult", "discreteval"), 
                      labels=c("PCR", "Discrete")))

然后,我们就可以制作剧情了。积分来自dat2。但是,在我们转向更宽之前,这些段来自数据对象。当两组不同的 y 点在不同的变量中时。然后您可以指定第二个轴,它实际上与主 y 轴具有相同的比例,但我们为不同的点颜色指定适当的断点和标签。

ggplot() + 
  geom_point(data=dat2, aes(x=var, y=vals, colour=discreteresult), show.legend = FALSE) + 
  geom_segment(data=dat, aes(x=factor(1, levels=1:2, labels=c("PCR", "Discrete")),
                              xend=factor(2, levels=1:2, labels=c("PCR", "Discrete")), 
                              y = PCRresult, yend=discreteval, 
                             colour=discreteresult), show.legend = FALSE) + 
  scale_y_continuous(sec.axis = sec_axis(trans = function(x){x}, breaks=x, labels=c("Positive", "Negative", "Fail"))) + 
  theme_bw() + 
  labs(x="condition", y="Value")

如果我误解了任务,我深表歉意,但我认为这就是您要找的。


编辑 - 添加了箱线图

要回答下面评论中有关添加箱线图的问题 - 您可以添加一个。基本上,诀窍是通过将 dat2 对象过滤为仅包含 PCR 的对象来制作 PCR 点的箱线图。然后您可以在箱线图几何中使用该数据,这将生成一个直接位于 PCR 点上方的箱线图。然后,您可以使用 position = position_nudge(x=-.5) 将箱线图移动到点的左侧。我还使用 coord_cartesian() 来设置情节的 x-limits。

ggplot() + 
  geom_point(data=dat2, aes(x=var, y=vals, colour=discreteresult), show.legend = FALSE) + 
  geom_segment(data=dat, aes(x=factor(1, levels=1:2, labels=c("PCR", "Discrete")),
                             xend=factor(2, levels=1:2, labels=c("PCR", "Discrete")), 
                             y = PCRresult, yend=discreteval, 
                             colour=discreteresult), show.legend = FALSE) + 
  geom_boxplot(data=filter(dat2, var=="PCR"), 
               aes(x=var, y=vals), 
               position=position_nudge(x=-.5), width=.5) + 
  scale_y_continuous(sec.axis = sec_axis(trans = function(x){x}, breaks=x, labels=c("Positive", "Negative", "Fail"))) + 
  theme_bw() + 
  coord_cartesian(xlim=c(0.75,1.5)) + 
  labs(x="condition", y="Value")