如何修复 R 中 ggplot2 的 geom_jitter() 不稳定的 y 位置?

How to fix unstable y-positions for geom_jitter() for ggplot2 in R?

我正在用箱线图做一个常见的 R ggplot2 图:箱线图补充了单个样本作为 geom_jitter() 所示的点,以显示每个组中的单个样本位置和数量。通常我没有注意到问题,但是根据最近的一些数据,我注意到抖动的 y 位置存在很大的不准确性和变化。但是,箱线图相对于 Y 保持稳定,geom_point() 在用于显示与抖动绘制相同的点时也是如此。当您有很多数据点时,错误可能不会引人注意,但如果需要对一组中的 5-10 个样本进行处理,如果您没有意识到这个问题,它可能会产生一个明显的错误,使绘图可能误导您.

我一开始以为这可能一直都在发生,我没有注意到,所以我做了一些随机数并用 geom_jitter() 做了一个 ggplot,但起初问题消失了。给出了一些示例数据和图表来显示正常情况和有问题的情况。

按预期工作的数据生成和绘图:

df <- data.frame("X" = rep("X", 5), "Y" = rnorm(5, 100, 30))

查看剧情:

library(ggplot2)
ggplot(df, aes(X, Y)) + geom_boxplot() + geom_jitter(col = "red") + geom_point(col = "blue")

红点和蓝点几乎完全对齐,如果您重复代码 5 次而没有注意到抖动点 y 位置的变化(仅沿 X 水平方向),您可以在 RStudio 预览中看到绘图轴,正如预期的那样)。在像下面这样有问题的情况下,您很快就会看到 y 轴点的变化,尤其是因为它有时会移动 y 轴的范围。

随着随机数的更多变化,我发现红点和蓝点之间存在明显差异,每次绘制相同数据时都会发生变化:

df <- data.frame("X" = rep("X", 5), "Y" = rnorm(5, 100, 400))

解决这个问题的实际人数是:

  X          Y
1 X  610.78026
2 X  -38.58905
3 X -196.00943
4 X   94.37797
5 X  415.58417

在我的结果中,最低点-196,有时约为-170,有时约为-250。 y 轴的范围每次都会发生变化。这类似于我在处理真实数据时遇到的问题。 我发现其他具有更多方差或点之间更大范围的数据测试并不能解释抖动 y 位置的发生变化。在某些方差较大的情况下,geom_jitter() 再次产生近乎完美的 y 位置。所以我想知道它是否与 ggplot2 使用的某些绘图区域的映射问题有关。我想通过使用 ylim(-206, 621) 强制 ggplot 保持相同的 ylimit 来测试它,但它未能阻止上述问题案例的区域。它给出了一个神秘但一致的错误:“警告消息:删除了 1 行包含缺失值 (geom_point)。” (在相应的图中,它丢失了 610.7 值的红色抖动点,尽管在图预览 window 中有足够的像素 space 蓝点和图表顶部之间还有大约 10 个点。在另一次尝试中,2个抖动点丢失,因为底部有时会超过下限)。

一个迂回的解决方案是为 X 组创建随机点,所有点都保持相同的 Y 和组标识,但效率不高。当在 X 上使用非数字组时,我发现对于添加的任何标签,它的数字位置都是 1。将以下内容添加到最后一个数据帧可提供正确的外观 + geom_point(aes(x= rnorm(5, 1, .2), y = Y), col = "yellow") - 但如果没有某种方法自动获取箱线图组的正确 X 位置,那么如果有很多组,这将变得非常麻烦。

要解决这个问题,任何关于问题原因的输入都会有很大帮助。

听起来你不想要默认的 geom_jitter 行为,默认情况下 "40% of the resolution of the data: this means the jitter values will occupy 80% of the implied bins."

对于像您这样的连续变量,“分辨率”是 "the smallest non-zero distance between adjacent values.

试试这个:

geom_jitter(col = "red", height = 0) + 

这将告诉 ggplot 在绘图之前您不希望对 y 值应用噪声。

另一种方法是在绘图步骤之前自己添加噪声,使您能够具体控制其分布和范围。

例如而不是让抖动填充一个统一的矩形:...

library(dplyr)
tibble(x = rep(1:2, each = 1000),
       y = rep(3:4, each = 1000)) -> point_data
  ggplot(point_data, aes(x,y)) + geom_jitter()

我们可以添加任何我们想要的噪声函数。在这里,没有特别的原因,我围绕真实数据制作甜甜圈,并将其与默认抖动进行比较:

point_data %>%
  mutate(angle = runif(2000, 0, 2*pi),
         dist  = rnorm(2000, 0.3, 0.05),
         x2    = x + dist*cos(angle),
         y2    = y + dist*sin(angle)) %>%
  ggplot() + 
    geom_jitter(aes(x,y), color = "red", alpha = 0.2) +
    geom_point(aes(x2,y2))