带有密度曲线的叠加直方图

Overlay histogram with density curve

提问人:Sacha Epskamp 提问时间:4/17/2011 最后编辑:B--rianSacha Epskamp 更新时间:9/23/2022 访问量:71725

问:

我正在尝试制作密度值的直方图,并将其与密度函数的曲线(不是密度估计)叠加。

使用一个简单的标准正态示例,以下是一些数据:

x <- rnorm(1000)

我可以做:

q <- qplot( x, geom="histogram")
q + stat_function( fun = dnorm )

但这给出了直方图的频率比例,而不是密度。我可以在直方图上获得适当的刻度:..density..

q <- qplot( x,..density.., geom="histogram")
q

但现在这给出了一个错误:

q + stat_function( fun = dnorm )

有什么我没有看到的吗?

另一个问题,有没有办法绘制函数的曲线,比如 ,但不是层?curve()

r ggplot2 直方图

评论

1赞 Ramnath 4/17/2011
问题是您已经使用 .. 为绘图定义了全局 y。密度。。里面。这让 .最简单的解决方法是编写 .请看下面的详细答案qplotstat_functionqplot(x, geom = 'blank') + geom_histogram(aes(y = ..density..)) + stat_function(fun = dnorm)
1赞 Ramnath 4/17/2011
等价于curve(dnorm, -4, 4)qplot(x = -4:4, stat = 'function', fun = dnorm, geom = 'line')
0赞 Sacha Epskamp 4/17/2011
啊,对了,我尝试将函数作为第一个参数,但现在看看出了什么问题。谢谢!

答:

60赞 Ramnath 4/17/2011 #1

给你!

# create some data to work with
x = rnorm(1000);

# overlay histogram, empirical density and normal density
p0 = qplot(x, geom = 'blank') +   
  geom_line(aes(y = ..density.., colour = 'Empirical'), stat = 'density') +  
  stat_function(fun = dnorm, aes(colour = 'Normal')) +                       
  geom_histogram(aes(y = ..density..), alpha = 0.4) +                        
  scale_colour_manual(name = 'Density', values = c('red', 'blue')) + 
  theme(legend.position = c(0.85, 0.85))

print(p0)

评论

8赞 Maxim.K 11/25/2013
P.S. 如果使用真实数据,请确保将经验平均值和 sd 参数传递给 dnorm 函数,请参阅语法stat_function帮助。
1赞 Jemus42 2/13/2014
只是出于好奇:如何使用 ggplot() 函数完成此操作?我只是勉强理解 ggplot() 的工作方式,所以我觉得用这种方法来做我的东西有点奇怪。
2赞 nzcoops 5/12/2014
@Jemus42你可以把第一行换成这样的内容 “ggplot(data.frame(x), aes(x=x)) +”
0赞 Shaun Jackman 1/30/2015
@Jemus42 这是为什么呢?如果不在 args 中传递 mean 和 sd 来stat_function我什么也得不到。
2赞 sunny 6/26/2015
叠加直方图和密度估计存在一个问题,即密度估计实际上应该移动半个二进制宽度,以实现最准确和美观的演示。我一直无法弄清楚如何做到这一点。有接受者吗?
46赞 Axeman 12/16/2015 #2

Ramnath 答案的更基本的替代方案,传递观察到的平均值和标准差,并使用 :ggplotqplot

df <- data.frame(x = rnorm(1000, 2, 2))

# overlay histogram and normal density
ggplot(df, aes(x)) +
  geom_histogram(aes(y = after_stat(density))) +
  stat_function(
    fun = dnorm, 
    args = list(mean = mean(df$x), sd = sd(df$x)), 
    lwd = 2, 
    col = 'red'
  )

enter image description here

评论

2赞 elcortegano 4/20/2018
这是一个非常方便的答案,因为它提供了一种绘制直方图和密度曲线的方法,即使它们属于不同的分布,如果需要(就像我一样)。谢谢!
0赞 Megatron 8/25/2021
最初的问题是关于拟合密度曲线,而不是专门拟合单个高斯曲线。如果要查看此解决方案不起作用的原因,请尝试将数据设置为df <- data.frame(x = c(rnorm(1000, 2, 2), rnorm(1000, 12, 2)))
0赞 Axeman 10/8/2021
@Megatron,不,OP要求密度函数的曲线(不是密度估计)”。所以我仍然认为这是正确的。您的示例表明,在某些情况下,正态密度函数可能不是对数据的良好描述,但这不是重点。
18赞 user29609 2/15/2019 #3

使用从呢?这样:geom_density()ggplot2

df <- data.frame(x = rnorm(1000, 2, 2))

ggplot(df, aes(x)) +
  geom_histogram(aes(y=..density..)) +  # scale histogram y
  geom_density(col = "red")

enter image description here

这也适用于多模式分布,例如:

df <- data.frame(x = c(rnorm(1000, 2, 2), rnorm(1000, 12, 2), rnorm(500, -8, 2)))

ggplot(df, aes(x)) +
  geom_histogram(aes(y=..density..)) +  # scale histogram y
  geom_density(col = "red")

enter image description here

评论

1赞 Axeman 7/18/2019
因为 OP 要求“密度函数的曲线(不是密度估计)”。 给出密度估计值。geom_density
6赞 David C 1/17/2020
也许不是OP所要求的,但这确实对我正在寻找的东西有所帮助!
2赞 Ben 3/16/2022
@Axeman 密度函数和密度估计有什么区别?
0赞 Bikash Pokharel 9/23/2022 #4

我正在尝试虹膜数据集。您应该能够在这些简单代码中看到所需的图形:

ker_graph <- ggplot(iris, aes(x = Sepal.Length)) + 
geom_histogram(aes(y = ..density..),
colour = 1, fill = "white") +
geom_density(lwd = 1.2,
linetype = 2,
colour = 2)