简体   繁体   English

在ggplot2中绘制多个密度:如何添加具有不同比例的额外变量?

[英]Plotting multiple densities in ggplot2: How to add an extra variable with a different scale?

I will try to describe my problem using a simplified example. 我将尝试使用简化示例来描述我的问题。 I am trying to plot several densities with ggplot2, something like: 我试图用ggplot2绘制几个密度,类似于:

library(reshape2)
library(ggplot2)

set.seed(1)
x <- replicate(5, rnorm(100)) 
colnames(x) <- paste0("x", 1:5)

ggplot(melt(x), aes(value, color = Var2)) + geom_density()

密度图

This works as expected. 这按预期工作。 Now, I would like to add a new variable with a very different scale: 现在,我想添加一个具有非常不同比例的新变量:

z <- cbind(x, y = rnorm(100) * 50)
ggplot(melt(z), aes(value, color = Var2)) + geom_density()

密度图与exrta变量

This produces the expected graph, but not the one I would like to make unfortunately. 这产生了预期的图形,但不幸的是我想要的图形。 I would like to keep the original scales of both axes, so that the differences between the first five densities would still be visible, and the density of the new variable would appear as flat. 我想保留两个轴的原始比例,以便前五个密度之间的差异仍然可见,并且新变量的密度将显示为平坦。

Is it possible to do this in a simple way? 是否可以以简单的方式做到这一点? Like telling ggplot to overlay the new density without changing the scaling? 就像告诉ggplot覆盖新密度而不改变缩放? Or telling ggplot to ignore a variable when computing the limits of the axes? 或者告诉ggplot在计算轴的极限时忽略变量?

I could consider a manual solution that would save the limits of the axes in a first step, and then specify them when the graph is made with the new variable. 我可以考虑一个手动解决方案,它将在第一步中保存轴的限制,然后在使用新变量创建图形时指定它们。 But that might not be the most elegant solution and might require a lot of extra code. 但这可能不是最优雅的解决方案,可能需要大量额外的代码。 I would prefer avoiding this kind of solution if possible (especially because my case is actually much more complex and implies multiple graphs with facet_wrap() ) 如果可能的话,我宁愿避免使用这种解决方案(特别是因为我的情况实际上要复杂得多,并且暗示了使用facet_wrap()多个图形)

Any suggestions or hints would be most welcome. 任何建议或提示都是最受欢迎的。 Many thanks in advance! 提前谢谢了!

PS: To give you more background information, I am trying to plot several posterior distributions against their prior distribution (the flat one). PS:为了给你更多背景信息,我试图根据他们之前的分布(平面分布)绘制几个后验分布。 I only have draws from the prior, not its exact density function - otherwise I would just have overlaid this prior with stat_function() . 我只有先前的绘制,而不是它的精确密度函数 - 否则我只是用stat_function()覆盖了这个先验。

Here's a cool way to change get a second Y axis: 这是一个很酷的方式来改变第二个Y轴:

First let's recreate your chart in a more generalized format. 首先,让我们以更通用的格式重新创建您的图表。 I'm going to create a data frame X (Note: it's Capitalized) 我打算创建一个数据框X(注意:它是大写的)

X <- data.frame(x)

g <- ggplot()
g <- g + geom_density(data = X, aes(x1, colour= "X1"))
g <- g + geom_density(data = X, aes(x2, colour= "x2"))
g <- g + geom_density(data = X, aes(x3, colour= "x3"))
g <- g + geom_density(data = X, aes(x3, colour= "x4"))

g

Which produces a the density chart 这产生了密度图表

在此输入图像描述

OK, cool now let's recreate the issue in z you mentioned 好的,现在很酷,让我们在你提到的z中重新创建问题

Z <- data.frame(z)

g <- ggplot()
g <- g + geom_density(data = Z, aes(x1, colour= "X1"))
g <- g + geom_density(data = Z, aes(x2, colour= "x2"))
g <- g + geom_density(data = Z, aes(x3, colour= "x3"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(y, colour= "y"))
g

Which gives 这使

在此输入图像描述

OK, now here's we can subset a second axis by the difference given in 好的,现在我们可以按照给出的差异对第二个轴进行子集化

z <- cbind(x, y = rnorm(100) * 50)

Namely, 50. but you can really make it whatever proportion you would like. 也就是说,但是你可以真正做到任何你想要的比例。

Z <- data.frame(z)

g <- ggplot()
g <- g + geom_density(data = Z, aes(x1, colour= "x1"))
g <- g + geom_density(data = Z, aes(x2, colour= "x2"))
g <- g + geom_density(data = Z, aes(x3, colour= "x3"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(y/50, colour= "y"))
g <- g + scale_y_continuous(sec.axis = sec_axis(~.*50, name= "Y Second Axis"))
g

Which gives us the desired double y axis! 这给了我们所需的双y轴!

在此输入图像描述

You can also do a double x axis as well. 您也可以执行双x轴。

g <- ggplot()
g <- g + geom_density(data = Z, aes(x1, colour= "x1"))
g <- g + geom_density(data = Z, aes(x2, colour= "x2"))
g <- g + geom_density(data = Z, aes(x3, colour= "x3"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(y/50, colour= "y"))
g <- g + scale_x_continuous(sec.axis = sec_axis(~.*50, name= "x Second Axis"))
g

在此输入图像描述

Hope that helps! 希望有所帮助!

Edit: 编辑:

After clarification it looks like the desired result would simply to keep the original x-axis limits but to add the new larger density. 澄清之后,看起来所需的结果只是为了保持原始的x轴限制,而是添加新的更大的密度。 We can do that both in my style and with the melt format you were using. 我们可以用我的风格和你使用的熔化格式来做到这一点。

g <- ggplot()
g <- g + geom_density(data = Z, aes(x1, colour= "x1"))
g <- g + geom_density(data = Z, aes(x2, colour= "x2"))
g <- g + geom_density(data = Z, aes(x3, colour= "x3"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(y, colour= "y"))
g <- g + xlim(range(-4:4))
g

OR 要么

ggplot(melt(z), aes(value, color = Var2)) + geom_density() + xlim(range(-4, 4)

在此输入图像描述

Edit 2: This gives us a plot with the right axis but it removes values from the density plot (as pointed out by Remek, and a solution in the comments which was correct from Jon Spring). 编辑2:这给了我们一个右轴的图,但是它从密度图中删除了值(正如Remek所指出的,以及Jon Spring中正确的注释中的解决方案)。 Can we get a plot that leaves the density values unchanged? 我们能得到一个能够保持密度值不变的图吗? Yes! 是! we need coord_cartesian() this will also us to preform a 'zoom in' rather than exude values outside of our limits. 我们需要coord_cartesian()这也是我们预先形成'放大'而不是超出我们极限的渗出值。

Here's the solution in both styles: 以下是两种风格的解决方案:

g <- ggplot()
g <- g + geom_density(data = Z, aes(x1, colour= "X1"))
g <- g + geom_density(data = Z, aes(x2, colour= "x2"))
g <- g + geom_density(data = Z, aes(x3, colour= "x3"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(y, colour= "y"))
g <- g + coord_cartesian(xlim=c(-4, 4))
g

ggplot(melt(z), aes(value, color = Var2)) + geom_density() + coord_cartesian(xlim=c(-4, 4))

both of which will produce the desired results! 这两者都会产生预期的效果! 在此输入图像描述

How about using the pre-combined data to specify range? 如何使用预组合数据指定范围?

ggplot(melt(z), aes(value, color = Var2)) + 
  geom_density() +
  coord_cartesian(xlim = c(min(melt(x)$value),
                           max(melt(x)$value)))

or, we could use the same melt(z) but back out the data with the new variable: 或者,我们可以使用相同的melt(z)但使用新变量退出数据:

ggplot(melt(z), aes(value, color = Var2)) + 
  geom_density() +
  coord_cartesian(xlim = c(min(subset(melt(z), Var2 != "y")$value),
                           max(subset(melt(z), Var2 != "y")$value)))

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM