繁体   English   中英

ggplot2 - 对齐箱线图中心的重叠点,并用线连接点

[英]ggplot2 - align overlayed points in center of boxplot, and connect the points with lines

我正在制作一个箱线图,其中点重叠,线连接两个时间集之间的点,下面提供的示例数据。

我有两个问题:

  1. 我希望这些点看起来像这样,只有一点高度抖动和更多宽度抖动。 但是,我希望这些点对称地集中在每个 y 轴 label 上的箱线图中间(以使图在视觉上更令人愉悦)。 例如,我希望将 y = 4 和 x = "后的 6 个数据点放置在箱线图中心右侧 3 处和中心左侧 3 处,距离中心对称距离。

  2. 另外,我希望线条与正确的点连接,但现在线条的开始和结束位置错误。 我知道我可以在 geom_point() 和 geom_line() 中使用 position = position_dodge() 来获得正确的位置,但我也希望能够按高度调整点(为什么点和线与 position_dodge() 对齐但是不是position_jitter?)。

这些事情有可能实现吗?

谢谢!

examiner <- rep(1:15, 2)
time <- rep(c("before", "after"), each = 15)
result <- c(1,3,2,3,2,1,2,4,3,2,3,2,1,3,3,3,4,4,5,3,4,3,2,2,3,4,3,4,4,3)
data <- data.frame(examiner, time, result)

ggplot(data, aes(time, result, fill=time)) + 
  geom_boxplot() +
  geom_point(aes(group = examiner), 
             position = position_jitter(width = 0.2, height = 0.03)) +
  geom_line(aes(group = examiner), 
            position = position_jitter(width = 0.2, height = 0.03), alpha = 0.3)

我不确定您是否可以同时满足您的两个问题。

  1. 您可以通过使用 geom_dotplot 来获得更“对称”的抖动,如下所示:
ggplot(data, aes(time, result, fill=time)) + 
  geom_boxplot() +
  geom_dotplot(binaxis="y", aes(x=time, y=result, group = time), 
             stackdir = "center", binwidth = 0.075)

问题是,当您添加线条时,它们将在原始的、未抖动的点处连接。

  1. 要将抖动点与 map 到抖动点的线连接起来,可以在绘图前将抖动添加到数据中。 如您所见,抖动都以不匹配的点和线结束。 请参阅将分组点与 ggplot中的线连接以获得更好的解释。
library(dplyr)

data <- data %>% 
  mutate(result_jit = jitter(result, amount=0.1),
         time_jit = jitter(case_when(
           time == "before" ~ 2,
           time == "after" ~ 1
         ), amount=0.1)
  )
         

ggplot(data, aes(time, result, fill=time)) + 
  geom_boxplot() +
  geom_point(aes(x=time_jit, y=result_jit, group = examiner)) +
  geom_line(aes(x=time_jit, y=result_jit, group = examiner), alpha=0.3)

结果

可以使用 ggplot_build() 从 geom_dotplot 中提取转换后的点 - 请参阅是否可以获得转换后的 plot 数据? (例如点 plot 中点的坐标,密度曲线)

这些点可以合并到原始数据上,用作 geom_line 的锚点。

把它们放在一起:

library(dplyr)
library(ggplot2)

examiner <- rep(1:15, 2)
time <- rep(c("before", "after"), each = 15)
result <- c(1,3,2,3,2,1,2,4,3,2,3,2,1,3,3,3,4,4,5,3,4,3,2,2,3,4,3,4,4,3)

# Create a numeric version of time
data <- data.frame(examiner, time, result) %>% 
  mutate(group = case_when(
           time == "before" ~ 2,
           time == "after" ~ 1)
  )

# Build a ggplot of the dotplot to extract data
dotpoints <- ggplot(data, aes(time, result, fill=time)) + 
  geom_dotplot(binaxis="y", aes(x=time, y=result, group = time), 
               stackdir = "center", binwidth = 0.075)

# Extract values of the dotplot
dotpoints_dat <- ggplot_build(dotpoints)[["data"]][[1]] %>% 
  mutate(key = row_number(),
         x = as.numeric(x),
         newx = x + 1.2*stackpos*binwidth/2) %>% 
  select(key, x, y, newx)

# Join the extracted values to the original data
data <- arrange(data, group, result) %>% 
  mutate(key = row_number())
newdata <- inner_join(data, dotpoints_dat, by = "key") %>% 
  select(-key)

# Create final plot
ggplot(newdata, aes(time, result, fill=time)) + 
  geom_boxplot() +
  geom_dotplot(binaxis="y", aes(x=time, y=result, group = time), 
               stackdir = "center", binwidth = 0.075) +
  geom_line(aes(x=newx, y=result, group = examiner), alpha=0.3)

结果

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM