使用ggplot2绘制概率图(而不是密度图)

7
我希望绘制数据,使y轴上的值为概率(在[0,1]范围内),x轴上的值为数据值。数据是连续的(也在[0,1]范围内),因此我想使用一些核密度估计函数并对其进行归一化,使得某个点x处的y值表示在输入数据中看到值x的概率。
所以,我想问:
a)这样合理吗?我知道我不能有看不到的值的概率,但我只是想使用核密度估计函数在我有的点之间进行插值,并在归一化后使用它。
b)ggplot中是否有任何内置选项可以用于覆盖geom_density()的默认行为,例如执行此操作?
提前感谢,
Timo
编辑:当我之前说“归一化”时,实际上我是指“缩放”。但我已经得到了答案,所以感谢大家帮我澄清这一点。

4
我不确定你所说的概率绘制是什么意思,但你提到想要对数据进行核平滑。核的作用是将经验分布(即直方图)转换为平滑的密度函数(即概率密度函数)。我认为你必须放弃核平滑要求或者不想绘制密度的愿望。虽然你可能在说“之后归一化”时已经考虑到了这一点。 - JD Long
谢谢你帮我澄清了思路。我认为在这种情况下,只使用直方图更加合适。如果我试图用平滑来绘制概率,我想我会让任何试图解释这些图的人感到困惑。 - Timo
3个回答

13

简单地合并 @JD Long 和 @yesterday 的回答:

ggplot(df, aes(x=x)) +
  geom_histogram(aes(y = ..density..), binwidth=density(df$x)$bw) +
  geom_density(fill="red", alpha = 0.2) +
  theme_bw() +
  xlab('') +
  ylab('')

在这里输入图片描述

这种方法通过density函数计算出ggplot2的binwidth,同时后者以透明度较高的方式画在直方图顶部。但你应该像 @yesterday 建议的那样进一步自定义,看看stat_densitiy


11

这不是ggplot的答案,但如果您想将核平滑和直方图的思想结合起来,可以采用自助法+平滑方法。做这样丑陋的事情会被统计学家痛批,因此请自行决定使用风险;)

从一些合成数据开始:

set.seed(1)
randomData <- c(rnorm(100, 5, 3), rnorm(100, 20, 3) )
hist(randomData, freq=FALSE)
lines(density(randomData), col="red")

enter image description here

密度函数有一个非常智能的带宽计算器,您可以从中借用:

bw <- density(randomData)$bw
resample <- sample( randomData, 10000, replace=TRUE)

然后使用带宽计算作为SD来制造一些随机噪声。

noise <- rnorm(10000, 0, bw)
hist(resample + noise, freq=FALSE)
lines(density(randomData), col="red")

enter image description here

嘿,看这里!一个核密度平滑的直方图!

我知道这个长回答并不是你问题的真正答案,但也许它会提供一些有创意的想法来滥用你的数据。


太棒了!你用这个非常巧妙的技巧实现了这个目标!谢谢你花时间和精力来分享。我明天一定会更深入地尝试它。与此同时,我会认真对待你关于遭到统计专家打击的警告 :) - Timo

7
你可以通过调用stat_density()而不是geom_density()来控制ggplot中密度/核估计的行为。
请参阅在线用户手册:http://had.co.nz/ggplot2/stat_density.html,你可以指定任何由stats::density()支持的核估计函数。
library(ggplot2)
df <- data.frame(x = rnorm(1000))
ggplot(df, aes(x=x)) + stat_density(kernel="biweight")

enter image description here


谢谢,虽然我的主要问题是如何缩放密度,以便之后它对应于在位置x发生的概率值。但正如@JDLong在上面评论所说,这种方法在大多数情况下并没有太多意义。 - Timo

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