ggplot2:具有正常曲线的直方图

Blo*_*omy 33 curve r ggplot2

我一直在尝试用ggplot 2在我的直方图上叠加一条正常曲线.

我的公式:

data <- read.csv (path...)

ggplot(data, aes(V2)) + 
  geom_histogram(alpha=0.3, fill='white', colour='black', binwidth=.04)
Run Code Online (Sandbox Code Playgroud)

我尝试了几件事:

+ stat_function(fun=dnorm)  
Run Code Online (Sandbox Code Playgroud)

....没有改变任何事情

+ stat_density(geom = "line", colour = "red")
Run Code Online (Sandbox Code Playgroud)

...在x轴上给了我一条直线红线.

+ geom_density()  
Run Code Online (Sandbox Code Playgroud)

对我不起作用,因为我想将我的频率值保持在y轴上,并且不需要密度值.

有什么建议?

提前感谢任何提示!

找到解决方案

+geom_density(aes(y=0.045*..count..), colour="black", adjust=4)

小智 19

想想我明白了:

set.seed(1)
df <- data.frame(PF = 10*rnorm(1000))
ggplot(df, aes(x = PF)) + 
    geom_histogram(aes(y =..density..),
                   breaks = seq(-50, 50, by = 10), 
                   colour = "black", 
                   fill = "white") +
stat_function(fun = dnorm, args = list(mean = mean(df$PF), sd = sd(df$PF)))
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 欢迎来到Stack Overflow,你能详细说明你的答案吗? (3认同)
  • 最好使用`ggsave()` - 减少代码,减少错误. (3认同)

JWi*_*man 17

这已经在这里回答,部分在这里.

如果您希望y轴具有频率计数,则需要根据观察数量和binwidth来缩放法线曲线.

library(ggplot2)

set.seed(1)
dat_hist <- data.frame(
  group = c(rep("A", 200), rep("B",150)),
  value = c(rnorm(200, 20, 5), rnorm(150,25,10)))

# Set desired binwidth and number of non-missing obs
bw = 2
n_obs = sum(!is.na(dat_hist$value))
Run Code Online (Sandbox Code Playgroud)

具有正常曲线的直方图

编辑

或者,对于允许使用构面并使用此处列出的方法的更灵活的方法,创建包含正常曲线的数据的单独数据集并覆盖这些数据.

g <- ggplot(dat_hist, aes(value))  + 
geom_histogram(aes(y = ..density..), binwidth = bw, colour = "black") + 
stat_function(fun = dnorm, args = list(mean = mean(dat_hist$value), sd = sd(dat_hist$value)))
Run Code Online (Sandbox Code Playgroud)


Pat*_*ckT 13

这是对JWilliman答案的延伸评论.我发现J的答案非常有用.在玩游戏时我发现了一种简化代码的方法.我不是说这是一种更好的方式,但我想我会提到它.

请注意,JWilliman的答案提供了y轴上的计数和"hack"来缩放相应的密度法线近似值(否则将覆盖总面积为1并因此具有更低的峰值).

这个评论的要点:内部更简单的语法stat_function,通过将所需的参数传递给美学功能,例如

aes(x = x, mean = 0, sd = 1, binwidth = 0.3, n = 1000)

这避免了必须传递args =,stat_function因此更加用户友好.好吧,它没有什么不同,但希望有人会发现它很有趣.

# parameters that will be passed to ``stat_function``
n = 1000
mean = 0
sd = 1
binwidth = 0.3 # passed to geom_histogram and stat_function
set.seed(1)
df <- data.frame(x = rnorm(n, mean, sd))

ggplot(df, aes(x = x, mean = mean, sd = sd, binwidth = binwidth, n = n)) +
    theme_bw() +
    geom_histogram(binwidth = binwidth, 
        colour = "white", fill = "cornflowerblue", size = 0.1) +
stat_function(fun = function(x) dnorm(x, mean = mean, sd = sd) * n * binwidth,
    color = "darkred", size = 1)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


dic*_*koa 8

这段代码应该这样做:

set.seed(1)
z <- rnorm(1000)

qplot(z, geom = "blank") + 
geom_histogram(aes(y = ..density..)) + 
stat_density(geom = "line", aes(colour = "bla")) + 
stat_function(fun = dnorm, aes(x = z, colour = "blabla")) + 
scale_colour_manual(name = "", values = c("red", "green"), 
                               breaks = c("bla", "blabla"), 
                               labels = c("kernel_est", "norm_curv")) + 
theme(legend.position = "bottom", legend.direction = "horizontal")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

注意:我使用的是qplot,但你可以使用更多功能的ggplot.

  • 这不是我正在寻找的,因为它为我提供了 y 轴上的密度值,我想将频率计数保留在那里! (2认同)
  • 我知道,但是频率和密度之间的"真实"区别是什么,毕竟它不是相同的信息......而且由于PDF的定义,密度更容易. (2认同)