ggplot2:如何在密度图中添加样本数量?

4

我试图生成一个带有样本量标签的(分组)密度图。

示例数据:

set.seed(100)
df <- data.frame(ab.class = c(rep("A", 200), rep("B", 200)),
                 val = c(rnorm(200, 0, 1), rnorm(200, 1, 1)))

未标记的密度图已生成,如下所示:
ggplot(df, aes(x = val, group = ab.class)) +
  geom_density(aes(fill = ab.class), alpha = 0.4)

密度示例

我的目标是在每个密度的峰值附近添加文字标签,显示每个组中的样本数量。然而,我无法找到正确的选项组合以此方式总结数据。

我尝试修改在箱线图上提出类似问题的答案中建议的代码:https://dev59.com/0WUo5IYBdhLWcg3w2CaJ#15720769

n_fun <- function(x){
  return(data.frame(y = max(x), label = paste0("n = ",length(x))))
}

ggplot(df, aes(x = val, group = ab.class)) +
  geom_density(aes(fill = ab.class), alpha = 0.4) +
  stat_summary(geom = "text", fun.data = n_fun)

但是,此时会出现错误:Error: stat_summary requires the following missing aesthetics: y

我还尝试在每个geom_density()stat_summary()图层中的aes()中添加y = ..density..,以及在ggplot()对象本身中添加,但都没有解决问题。

我知道可以通过为每个组手动添加标签来实现,但我希望有一种通用的解决方案,例如允许使用aes()设置标签颜色以匹配密度。

我错在哪里了?

1个回答

3
fun.data的返回值中的y并不是aes。在ggplot(df, aes(x = val, group = ab.class, y =或者stat_summary(aes(y =中全局设置中没有指定y时,stat_summary会报错无法找到y。通过aes从数据中获取yfun.data计算在每个x上要显示点/文本等的位置。

即使你已经通过aes指定了y,也无法得到期望的结果,因为stat_summary会在每个x上计算一个y

但是,你可以通过geom_textannotate将文本添加到所需的位置:

# save the plot as p
p <- ggplot(df, aes(x = val, group = ab.class)) +
    geom_density(aes(fill = ab.class), alpha = 0.4)

# build the data displayed on the plot.
p.data <- ggplot_build(p)$data[[1]]

# Note that column 'scaled' is used for plotting
# so we extract the max density row for each group
p.text <- lapply(split(p.data, f = p.data$group), function(df){
    df[which.max(df$scaled), ]
})
p.text <- do.call(rbind, p.text)  # we can also get p.text with dplyr.

# now add the text layer to the plot
p + annotate('text', x = p.text$x, y = p.text$y,
             label = sprintf('n = %d', p.text$n), vjust = 0)

enter image description here


1
当您想要访问由ggplot本身计算的数据时,这非常有用。 - mt1022

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接