geom_density returns 不考虑实际值的绘图

geom_density returns plot without considering real values

我正在尝试为 7 个不同地理点上的 3 个变量绘制密度图,但输出未按预期显示。 N应该在中间较高,但另一个似乎在不真实时绘制相同的图案,这是为什么?我该如何解决?

Variable1 <- c(rep("E",7), rep("N",7),rep("L",7))
Variable2 <- c(rep(1:7, 3))
value <- c(12.44035, 11.98035333, 11.40821, 12.15833, 13.14826, 11.99339667, 12.17363, 4.073096, 3.946134667, 6.244152, 5.76892, 4.545772, 3.580206667, 2.879470667, 3.6912875, 3.501247, 2.684179, 3.06306, 3.364774, 4.485021333, 3.373649333)
df <- data.frame(Variable1, Variable2, value)

library(ggridges)
ggplot(df, aes(x = Variable2, y = Variable1)) +
  geom_density_ridges(aes(fill = Variable1)) 

我想要这样的东西:

您正在计算 x-axis 的密度,在您的情况下是 Variable 2,每个 Variable 1 的密度相同 (1,2,...,7),因此它给出密度相同。

所以我认为您希望 x-axis 为 value,但实际上您不需要 Variable 2,因为它只是一个索引。

ggplot(df, aes(x=value, y=Variable1)) +
  geom_density_ridges(aes(fill=Variable1)) 

编辑 1:

您实际上想要的几何是 geom_line,或 geom_smooth(用于更漂亮的图形),或者 geom_area 用于填充曲线下的区域。

现在,一种方法是将所有曲线放在相同的 y 轴上:

ggplot(df, aes(x=Variable2, y=value, color=Variable1)) +
  geom_smooth(fill=NA)

但这并没有提供您想要的分离效果。要做到这一点,我知道的方法是为每个 Variable1 绘制一个图,并将它们排列在一起(但也许这个包 ggridges 有一个选项,但我从未使用过它)。为此,我们构建了一个“基础”图:

g = ggplot(df, aes(x=Variable2, y=value)) +
  geom_smooth(fill=NA) +
  theme(axis.text.x  = element_blank(),
        axis.title.x = element_blank())

我们删除了 x-axis 以便在网格中仅添加一次。然后,我们为每个变量应用该基数,一次一个,使用 for 循环:

for(i in unique(df$Variable1)){
  df2 = df[df$Variable1==i,]
  assign(i,
         g %+% df2 + ylab(i) +
               ylim(min(df2$value),max(df2$value)))}

这为每个 Variable1 创建一个图表,命名为变量本身。现在我们在最后一个图中添加 x-axis 并将它们排列在一起:

N = N + theme(axis.text.x  = element_text(),
              axis.title.x = element_text())

gridExtra::grid.arrange(E,L,N, nrow=3)

输出:

编辑 2:

要使用颜色,首先我们不要将 geom 传递给 g:

g = ggplot(df, aes(x=Variable2, y=value)) +
  theme(axis.text.x  = element_blank(),
        axis.title.x = element_blank())

然后我们创建一个我们将在循环中使用的颜色向量:

color = c("red", "green", "blue")
names(color) = unique(df$Variable1)

然后我们将 color 参数传递到我们之前省略的 geom 中。

但首先,让我谈谈可用的 geoms:我们可以使用平滑的 geom 区域,它会给出如下内容:

这很好,但图表下方有很多无用区域。要更改它,我们可以使用 geom_ribbon,其中我们可以使用参数 aes(ymin=min(value)-0.1, ymax=value)ylim(min(df2$value)-0.1, max(df2$value)) 将图形停止在最小值(负 0.1)处。问题是 ggplot 的平滑功能不能很好地与 geom_ribbon 一起使用,所以我们只能选择“粗略”图形:

smoot 区域代码:

for(i in unique(df$Variable1)){
  df2 = df[df$Variable1==i,]
  assign(i,
         g %+% df2 + ylab(i) +
         stat_smooth(geom="area", fill=color[i]))}

粗色带代码:

for(i in unique(df$Variable1)){
  df2 = df[df$Variable1==i,]
  assign(i,
         g %+% df2 + ylab(i) + ylim(min(df2$value)-0.1,max(df2$value)) +
         geom_ribbon(aes(ymax=value, ymin=min(value)-0.1), fill=color[i]))}

我搜索了一种方法来解决这个棘手的问题,但一无所获,我会在网站上创建一个问题,如果我找到解决方案,我会在此处显示!

编辑 3:

中询问后,我发现在 stat_smooth(geom="ribbon", aes(...))aes 参数中使用 after_stat 可以解决它(更多信息请阅读 link) .

for(i in unique(df$Variable1)){
  df2 = df[df$Variable1==i,]
  assign(i,
         g %+% df2 + ylab(i) + 
           stat_smooth(geom="ribbon", fill=color[i],
                       aes(ymax=after_stat(value), ymin=after_stat(min(value))-0.1)))}