【问题标题】:R control jitter function - avoid overplotting / non-random jitterR 控制抖动功能 - 避免过度绘图/非随机抖动
【发布时间】:2021-06-10 22:40:15
【问题描述】:

我的问题看起来很简单,我使用 ggplot2geom_jitter() 来绘制变量。 (以我的照片为例)

Jitter 现在为变量添加了一些随机噪声(在本示例中,该变量仅称为“1”)以防止过度绘图。所以我现在在 y 方向上有随机噪声,很明显,否则会被完全重叠的部分现在更清晰了。

但这是我的问题:

如您所见,仍有一些点相互重叠。在我这里的示例中,如果它不是 y 方向上的随机噪声,则可以很容易地防止这种情况......但以某种方式更具战略性地放置偏移量。

我能否以某种方式改变geom_jitter() 的行为,或者 ggplot2 中是否有类似的功能可以做到这一点?

不是真正的最小示例,但也不会太长:

library("imputeTS")
library("ggplot2")

data <- tsAirgap


# 2.1 Create required data

# Get all indices of the data that comes directly before and after an NA

na_indx_after <- which(is.na(data[1:(length(data) - 1)])) + 1
# starting from index 2 moves all indexes one in front, so no -1 needed for before
na_indx_before <- which(is.na(data[2:length(data)]))

# Get the actual values to the indices and put them in a data frame with a label
before <- data.frame(id = "1", type = "before", input = na_remove(data[na_indx_before]))
after <- data.frame(id = "1", type = "after", input = na_remove(data[na_indx_after]))
all <- data.frame(id = "1", type = "source", input = na_remove(data))

# Get n values for the plot labels
n_before <- length(before$input)
n_all <- length(all$input)
n_after <- length(after$input)



# 2.4 Create dataframe for ggplot2

# join the data together in one dataframe
df <- rbind(before, after, all)


# Create the plot

gg <- ggplot(data = df) +
  geom_jitter(mapping = aes(x = id, y = input, color = type, alpha = type), width = 0.5 , height = 0.5) 

gg <- gg + ggplot2::scale_color_manual(
  values = c("before" = "skyblue1", "after" = "yellowgreen","source" = "gray66"),
)

gg <- gg + ggplot2::scale_alpha_manual(
  values = c("before" = 1, "after" = 1,"source" = 0.3),
)

gg + ggplot2::theme_linedraw() + theme(aspect.ratio = 0.5) + ggplot2::coord_flip()

这么多好的建议......这是 Bens 的建议在我的示例中的样子:

我将部分代码更改为:

gg <- ggplot(data = df, aes(x = input,  color = type, fill = type, alpha = type)) +
  geom_dotplot(binwidth = 15) 

基本上也可以按我的预期工作。 Jon 建议的 ggbeeplot 对我的目的也很有效。

【问题讨论】:

  • 我不知道 ggplot2 内置的任何东西可以做到这一点。您可能会查看 ggbeeswarm 包以获取有关此选项的一些选项。但这可能不是您想要的,因为它将所有点集中到中心线。您可以交替定义一个准随机函数来执行此操作,例如使用poissonedpoissondisc 包。或者,如果您想矫枉过正,您可以使用particles 创建一个模拟来排斥任何重叠点。
  • 请给我们一个minimal reproducible example好吗?我认为ggplot(df, aes(x, y, color = col, fill=col)) + geom_dotplot(stackdir="center",binwidth=0.1, alpha=0.5) 可以工作(使用@JonSpring 的示例,但我认为它不适用于变量y
  • 你们帮了大忙!我显然很难找到合适的谷歌条款。 Ben 的解决方案也非常适合我的目的(请参阅我编辑的答案)。 Ben,您也可以将此添加为答案。这里的好处是它不需要 ggplot2 之外的额外包。但我也非常喜欢 ggbeeswarm 软件包带来的所有可能性。完美,我已经从没有令人满意的解决方案转变为在 1 天内从多个不错的解决方案中进行选择。非常感谢。

标签: r ggplot2 data-visualization jitter


【解决方案1】:

我想到了一个我非常喜欢的 hack,使用 ggrepel。它通常用于标签,但没有什么能阻止您将标签变成一个点。

df <- data.frame(x = rnorm(200),
                 col = sample(LETTERS[1:3], 200, replace = TRUE),
                 y = 1)

ggplot(df, aes(x, y, label = "●", color = col)) + # using unicode black circle
  ggrepel::geom_text_repel(segment.color = NA, 
                           box.padding = 0.01, key_glyph = "point")

这种方法的一个缺点是 ggrepel 可能会花费大量时间来处理大量点,并且每次更改绘图大小时都会以不同的方式重新计算。更快的替代方法是使用ggbeeswarm::geom_quasirandom,它使用确定性过程来定义看起来随机的抖动。

ggplot(df, aes(x,y, color = col)) +
  ggbeeswarm::geom_quasirandom(groupOnX = FALSE)

【讨论】:

  • 很好,但似乎只有在没有太多点的情况下才有效。否则我会得到“ggrepel:95 个未标记的数据点(重叠太多)。考虑增加 max.overlaps”,它只是不会打印所有点。也不知道幕后实际做了什么(添加到情节中的内容),但情节需要很长时间才能加载(切换情节时)。您的 ggbeeswarm 建议虽然效果很好(也许您还想将此添加到答案中或作为附加答案,我可以接受)。非常感谢您的帮助,乔恩!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-21
  • 2011-03-08
  • 1970-01-01
  • 2017-04-24
  • 2020-01-15
  • 1970-01-01
  • 2014-08-22
相关资源
最近更新 更多