【问题标题】:Kernel density plot bandwidth in ggplot2 with `facet_wrap`带有`facet_wrap`的ggplot2中的内核密度图带宽
【发布时间】:2011-04-27 13:44:49
【问题描述】:

我想在ggplot2 包中使用stat_density()facet_wrap() 为不同的分组创建内核密度图,但我想确保我对每个图使用相同的带宽。我可以确定stat_density() 对每个地块使用相同的带宽吗?

例如,使用diamonds:

library(ggplot2)    
ggplot(diamonds, aes(x = carat)) + 
  stat_density() + 
  facet_wrap(~ cut) + 
  scale_x_log()

在文档中它显示我可以使用adjust 来调整自动带宽,但这只是应用倍数并让我回到原来的问题。 stat_density() 也有... 选项,但我一直无法通过density() 选项bw,像这样:

ggplot(diamonds, aes(x = carat)) + 
  stat_density(bw = 1) + 
  facet_wrap(~ cut) + 
  scale_x_log()

那么,如果stat_density() 没有在所有方面使用相同的带宽,有没有办法可以强制这样做?我用transform()density() 尝试了ddply() 解决方案,但这失败了,因为density() 不一定返回与输入相同数量的x 和y 值。有任何想法吗?谢谢!

编辑 看起来ggplot2 为每个方面分配了最佳带宽(看起来@Ramnath 和 Dianardo、Fortin 和 Lemieux Econometrica 1996 同意这一点),而不是我寻求的恒定带宽。但是,如果我确实想要所有方面的带宽恒定,那么我在下面的尝试会失败。

my.density <- function(x) {
    temp <- density(x$carat, bw = 0.5)
    return(data.frame(carat = temp$x, density = temp$y))
}
temp <- ddply(diamonds, .(cut), my.density)
ggplot(temp, aes(x = carat, y = density)) + 
             geom_point() + 
             facet_wrap(~ cut) + 
             scale_x_log()
Warning messages:
1: In match.fun(get(".transform", .))(values) : NaNs produced
2: In match.fun(get(".transform", .))(values) : NaNs produced
3: In match.fun(get(".transform", .))(values) : NaNs produced
4: In match.fun(get(".transform", .))(values) : NaNs produced
5: In match.fun(get(".transform", .))(values) : NaNs produced
6: Removed 84 rows containing missing values (geom_point). 
7: Removed 113 rows containing missing values (geom_point). 
8: Removed 98 rows containing missing values (geom_point). 
9: Removed 98 rows containing missing values (geom_point). 
10: Removed 106 rows containing missing values (geom_point). 

【问题讨论】:

  • 查看stat_density 的文档,它似乎使用了density 的默认版本。进一步挖掘,查看density 的文档,您会发现它使用bw.nrd0 方法来计算带宽。您应该查看此描述并弄清楚如何预先转换您的数据,以便您能够实现您的目标。
  • @Ramnath -- 谢谢!我沿着那条路走,但我自己无法更接近答案。但也许这会产生我的基本问题,“哪些stat_density() 参数是使用来自所有方面的信息设置的?哪些是在每个方面设置的?”
  • @richardh -- 我认为统计转换是在对数据进行分面后应用的。因此,如果bw.nrd0 方法根据数据计算带宽,那么您将在各个方面拥有不同的带宽。为了获得更多控制,我的建议是使用ddply 并根据需要计算密度估计值,然后将其作为aesthetic 传递给ggplot。如果你愿意,我可以做一个例子。出于好奇,您为什么要在所有地块上使用相同的带宽?
  • @Ramnath -- 关于带宽的要点!我检查了这项技术的“参考”(Dinardo、Fortin 和 Lemieux Econometrica 1996),看起来他们确实使用了可变带宽,为每个方面进行了最佳设置。我会确保我们真的想要恒定的带宽。但是对于我自己的教育,我很想看看你会怎么做——我的方法失败了(我会在上面粘贴)。
  • @richard -- 实际上警告是由于my.densitycarat 的负值。稍微修改一下你的代码就可以了:ggplot(temp, aes(x = carat, y = density)) + geom_line(subset = .(carat &gt; 0)) + facet_wrap(~ cut) + scale_x_log()。让我知道这是否是您要找的东西

标签: r ggplot2


【解决方案1】:

警告是由于my.density 中的carat 为负值。稍微修改一下你的代码就可以了:

  ggplot(temp, aes(x = carat, y = density)) + 
    geom_line(subset = .(carat > 0)) +
   facet_wrap(~ cut) + scale_x_log() 

希望对你有用

【讨论】:

  • 从技术上讲,使用密度估计器会更好,它允许您修复估计密度的范围。
猜你喜欢
  • 2016-07-19
  • 2014-05-26
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-11
  • 2015-10-07
  • 1970-01-01
相关资源
最近更新 更多