【问题标题】:Plotting the normal and binomial distribution in same plot在同一图中绘制正态分布和二项式分布
【发布时间】:2020-06-18 03:15:55
【问题描述】:

正如标题所示,我正在尝试使用 R 在同一个图中绘制正态分布和二项式分布。我的尝试如下所示,我的正态分布看起来如此不正确有什么原因吗?我已经仔细检查了平均值和标准差,一切看起来都很好。

n <- 151
p <- 0.2409

dev <- 4
mu <- n*p
sigma <- sqrt(n*p*(1 - p))

xmin <- round(max(mu - dev*sigma,0));
xmax <- round(min(mu + dev*sigma,n))
x <- seq(xmin, xmax)
y <- dbinom(x,n,p)

barplot(y, 
     col = 'lightblue',
     names.arg = x,
     main = 'Binomial distribution, n=151, p=.803')

range <- seq(mu - dev*sigma, mu + dev*sigma, 0.01)
height <- dnorm(range, mean = mu, sd = sigma) 
lines(range, height, col = 'red', lwd = 3)

【问题讨论】:

标签: r plot distribution normal-distribution


【解决方案1】:

barplot 对您的情况来说是错误的功能。或者,如果您真的想使用它,则必须在 barplotlines 之间重新调整 x 轴

barplot 的默认值是将每个 height 值放在

head(c(barplot(y, plot = FALSE)))
# [1] 0.7 1.9 3.1 4.3 5.5 6.7

这可以通过您选择 spacewidth 或两者的组合来更改

head(c(barplot(y, plot = FALSE, space = 0)))
# [1] 0.5 1.5 2.5 3.5 4.5 5.5

head(c(barplot(y, plot = FALSE, space = 0, width = 3)))
# [1]  1.5  4.5  7.5 10.5 13.5 16.5

您可以使用plot 来避免处理这些事情

n <- 151
p <- 0.2409

dev <- 4
mu <- n*p
sigma <- sqrt(n*p*(1 - p))

xmin <- round(max(mu - dev*sigma,0));
xmax <- round(min(mu + dev*sigma,n))
x <- seq(xmin, xmax)
y <- dbinom(x,n,p)

plot(x, y, type = 'h', lwd = 10, lend = 3, col = 'lightblue',
     ann = FALSE, las = 1, bty = 'l', yaxs = 'i', ylim = c(0, 0.08))
title(main = sprintf('Binomial distribution, n=%s, p=%.3f', n, p))
lines(x, dnorm(x, mean = mu, sd = sigma), col = 'red', lwd = 7)

xx <- seq(min(x), max(x), length.out = 1000)
lines(xx, dnorm(xx, mean = mu, sd = sigma), col = 'white')

此图中的“条”取决于您选择的lwd 和您的设备尺寸,但如果您需要更好地控制它,您可以使用rect,这需要更多的工作。

w <- 0.75
plot(x, y, type = 'n', ann = FALSE, las = 1, bty = 'l', yaxs = 'i', ylim = c(0, 0.08))
rect(x - w / 2, 0, x + w / 2, y, col = 'lightblue')
lines(xx, dnorm(xx, mean = mu, sd = sigma), col = 'red', lwd = 3)
title(main = sprintf('Binomial distribution, n=%s, p=%.3f', n, p))

【讨论】:

    【解决方案2】:

    您可以使用ggplot2

    library(ggplot2)
    
    n <- 151
    p <- 0.2409
    mean <- n*p
    sd <-   sqrt(n*p*(1-p))
    binwidth <-   0.005
    
    
    xmin <- round(max(mu - dev*sigma,0));
    xmax <- round(min(mu + dev*sigma,n))
    x <- seq(xmin, xmax)
    y <- dbinom(x,n,p)
    
    df <- cbind.data.frame(x, y)
    
    ggplot(df, aes(x = x, y = y)) +
      geom_bar(stat="identity", fill = 'dodgerblue3')+
      labs(title = "Binomial distribution, n=151, p=.803",
           x = "",
           y = "") +
      theme_minimal()+
      # Create normal curve, akousting for number of observations and binwidth
      stat_function( 
        fun = function(x, mean, sd, n, bw){ 
          dnorm(x = x, mean = mean, sd = sd)
        }, col = "red", size=I(1.4),  
        args = c(mean = mean, sd = sd, n = n, bw = binwidth))
    

    【讨论】:

    • Rlover 删除 * n * bw 使其完美契合
    • 太棒了,我已经编辑了我的答案以反映您的建议
    【解决方案3】:

    您可以使用ggplot2 包来做到这一点(我对正态分布感到惊讶,但用 geom_point 替换 geom_line 让我确信它具有这种形式(方差是否太高?)):

    n <- 151
    p <- 0.2409
    
    dev <- 4
    mu <- n*p
    sigma <- sqrt(n*p*(1 - p))
    
    xmin <- round(max(mu - dev*sigma,0));
    xmax <- round(min(mu + dev*sigma,n))
    
    x <- seq(xmin, xmax)
    y <- dbinom(x,n,p)
    
    z <- dnorm(x = qnorm(p = seq(0,1, length.out = length(x)), mean = mu, sd = sigma), mean = mu, sd = sigma)
    
    library(magrittr)
    library(ggplot2)
    data.frame(x, y, z) %>% 
        ggplot(aes(x = x)) +
        geom_col(aes(y = y)) +
        geom_line(aes(x = x, y = z, colour = "red"),
              show.legend = FALSE)
    

    【讨论】:

    • 为什么形状与 OP 的形状如此不同?另外顺便说一句,您加载 magrittr 只是为了获取管道运算符,如果您只是将数据框直接用作 ggplot 的第一个参数,则不需要这样做
    • 1) 这是因为使用了方差公式(这是一个不正确的公式)。 2)我相信向非 tidyverse 用户展示管道操作员作为 ggplot 使用(文学编程)之外的正确做法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-07
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多