首页 > 解决方案 > 如何修复 R 中 ggplot2 的 geom_jitter() 的不稳定 y 位置?

问题描述

我正在用箱线图制作一个常见的 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 轴水平)。在像下面这样的有问题的情况下,您很快就会看到 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 使用的某些绘图区域的映射问题有关。我想通过强制 ggplot 保持相同的 ylimit 来测试它ylim(-206, 621)但它未能通过上述有问题的案例阻止该地区。它给出了一个神秘但一致的错误:“警告消息:删除了 1 行包含缺失值 (geom_point)。” (在相应的图中,它丢失了 610.7 值的红色抖动点,尽管在绘图预览窗口中有足够的像素空间在蓝点和图形顶部之间还有大约 10 个点。在另一次尝试中,得到 2 个抖动点丢失,因为底部有时会超过下限)。

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

为了解决这个问题,任何关于它的原因是什么的输入都会有很大的帮助。

标签: rggplot2jitter

解决方案


听起来你不想要默认geom_jitter行为,它在绘图之前分别向 x 和 y 值添加均匀分布的噪声量,默认情况下“数据分辨率的 40%:这意味着抖动值将占据 80%的隐含垃圾箱。”

对于像您这样的连续变量,“分辨率”是“相邻值之间的最小非零距离。

试试这个:

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))

在此处输入图像描述


推荐阅读