【问题标题】:Predicted values for logistic regression from glm and stat_smooth in ggplot2 are differentggplot2 中 glm 和 stat_smooth 的逻辑回归预测值不同
【发布时间】:2012-02-09 08:15:31
【问题描述】:

我正在尝试在ggplot2 中制作这个逻辑回归图。

df <- structure(list(y = c(2L, 7L, 776L, 19L, 12L, 26L, 7L, 12L, 8L,
24L, 20L, 16L, 12L, 10L, 23L, 20L, 16L, 12L, 18L, 22L, 23L, 22L,
13L, 7L, 20L, 12L, 13L, 11L, 11L, 14L, 10L, 8L, 10L, 11L, 5L,
5L, 1L, 2L, 1L, 1L, 0L, 0L, 0L), n = c(3L, 7L, 789L, 20L, 14L,
27L, 7L, 13L, 9L, 29L, 22L, 17L, 14L, 11L, 30L, 21L, 19L, 14L,
22L, 29L, 28L, 28L, 19L, 10L, 27L, 22L, 18L, 18L, 14L, 23L, 18L,
12L, 19L, 15L, 13L, 9L, 7L, 3L, 1L, 1L, 1L, 1L, 1L), x = c(18L,
19L, 20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L,
32L, 33L, 34L, 35L, 36L, 37L, 38L, 39L, 40L, 41L, 42L, 43L, 44L,
45L, 46L, 47L, 48L, 49L, 50L, 51L, 52L, 53L, 54L, 55L, 56L, 59L,
62L, 63L, 66L)), .Names = c("y", "n", "x"), class = "data.frame", row.names = c(NA,
-43L))


mod.fit <- glm(formula = y/n ~ x, data = df, weight=n, family = binomial(link = logit),
        na.action = na.exclude, control = list(epsilon = 0.0001, maxit = 50, trace = T))
summary(mod.fit)

Pi <- c(0.25, 0.5, 0.75)
LD <- (log(Pi /(1-Pi))-mod.fit$coefficients[1])/mod.fit$coefficients[2]
LD.summary <- data.frame(Pi , LD)
LD.summary


plot(df$x, df$y/df$n, xlab = "x", ylab = "Estimated probability")

lin.pred <- predict(mod.fit)
pi.hat <- exp(lin.pred)/(1 + exp(lin.pred))
lines(df$x, pi.hat, lty = 1, col = "red")


segments(x0 = LD.summary$LD, y0 = -0.1, x1 = LD.summary$LD, y1 = LD.summary$Pi,
         lty=2, col=c("darkblue","darkred","darkgreen"))
segments(x0 = 15, y0 = LD.summary$Pi, x1 = LD.summary$LD, y1 = LD.summary$Pi,
         lty=2, col=c("darkblue","darkred","darkgreen"))
legend("bottomleft", legend=c("LD25", "LD50", "LD75"), lty=2, col=c("darkblue","darkred","darkgreen"), bty="n", cex=0.75)

这是我对ggplot2的尝试

library(ggplot2)

p <- ggplot(data = df, aes(x = x, y = y/n)) +
            geom_point() +
            stat_smooth(method = "glm", family = "binomial")

p <- p + geom_segment(aes(
                            x = LD.summary$LD
                          , y = 0
                          , xend = LD.summary$LD
                          , yend = LD.summary$Pi
                         )
                         , colour="red"
                       )

p <- p + geom_segment(aes(
                            x = 0
                          , y = LD.summary$Pi
                          , xend = LD.summary$LD
                          , yend = LD.summary$Pi
                         )
                         , colour="red"
                       )

print(p)

问题

  1. glmstat_smooth 的预测值看起来不同。这两种方法会产生不同的结果还是我在这里遗漏了什么。
  2. 我的 ggplot2 图与基本 R 图不完全一样。
  3. ggplot2中线段如何使用不同的颜色?
  4. 以及如何将图例放入ggplot2?

提前感谢您的帮助和时间。谢谢

【问题讨论】:

  • 您的基本 R 图片中没有图例(尽管命令很好) - 我会更新它以避免混淆。
  • @mathematical.coffee:感谢您的评论。请参阅左下角的图例。
  • 是的,那是因为我更新了图片以包含图例。
  • 哎呀,谢谢@mathematical.coffee
  • 为什么在赋值Pi &lt;- c(0.25, 0.5, 0.75) 中将变量称为“Pi”? Pi是什么的快捷方式? “LD”也一样?

标签: r ggplot2


【解决方案1】:

只是对@mathetmatical.coffee 的回答进行了一些小的补充。通常,geom_smooth 不应该取代实际建模,这就是为什么当您想要使用从glm 等获得的特定输出时,它有时会显得不方便。但实际上,我们需要做的就是将拟合值添加到我们的数据框中:

df$pred <- pi.hat
LD.summary$group <- c('LD25','LD50','LD75')

ggplot(df,aes(x = x, y = y/n)) + 
    geom_point() + 
    geom_line(aes(y = pred),colour = "black") + 
    geom_segment(data=LD.summary, aes(y = Pi,
                                      xend = LD,
                                      yend = Pi,
                                      col = group),x = -Inf,linetype = "dashed") + 
    geom_segment(data=LD.summary,aes(x = LD,
                                     xend = LD,
                                     yend = Pi,
                                     col = group),y = -Inf,linetype = "dashed")

最后一个小技巧是使用Inf-Inf 让虚线一直延伸到情节边界。

这里的教训是,如果您只想为绘图添加平滑,而绘图中没有其他内容依赖于它,请使用geom_smooth。如果您想参考拟合模型的输出,通常更容易将模型拟合到 ggplot 之外然后进行绘图。

【讨论】:

  • 优雅的答案。感谢您的帮助。
  • 上述代码中变量“Pi”和“LD”代表什么?
  • @ErdoganCEVHER 为了让这个特定的代码示例工作,调用变量是否有所不同? (通常,“LD50”是我见过的一个术语,指的是 50% 人口的致死剂量,但我认为它与这个问题没有太大关系。)
  • 绝对不是!我认为 LD 是“对数差异”,在尝试将代码与理论联系起来时遇到了麻烦。谢谢解释。也许,OP 提问者中的一些简单的 cmets 在理论代码连接方面会有所帮助。
【解决方案2】:

修改您的LD.summary 以包含一个带有group(或适当标签)的新列。

LD.summary$group <- c('LD25','LD50','LD75')

然后修改您的geom_segment 命令以在其中包含col=LD.summary$group(并删除colour="red"),它以不同的颜色绘制每个段并添加一个图例:

geom_segment( aes(...,col=LD.summary$group) )

另外,为了避免一直使用LD.summary$xxx,请将data=LD.summary 输入到您的geom_segment

geom_segment(data=LD.summary, aes(x=0, y=Pi,xend=LD, yend=Pi, colour=group) )

至于为什么图表不完全相同,在基础 R 图中,x 轴从 ~20 开始,而在ggplot 中,它从零开始。这是因为您的第二个 geom_segmentx=0 开头。 要解决此问题,您可以将 x=0 更改为 x=min(df$x)

要获取您的 y 轴标签,请使用 + scale_y_continuous('Estimated probability')

总结:

LD.summary$group <- c('LD25','LD50','LD75')
p <- ggplot(data = df, aes(x = x, y = y/n)) +
            geom_point() +
            stat_smooth(method = "glm", family = "binomial") +
            scale_y_continuous('Estimated probability')    # <-- add y label
p <- p + geom_segment(data=LD.summary, aes( # <-- data=Ld.summary
                            x = LD
                          , y = 0
                          , xend = LD
                          , yend = Pi
                          , col = group     # <- colours
                         )
                       )    
p <- p + geom_segment(data=LD.summary, aes( # <-- data=Ld.summary
                            x = min(df$x)   # <-- don't plot all the way to x=0
                          , y = Pi
                          , xend = LD
                          , yend = Pi
                          , col = group     # <- colours
                         )
                       )
print(p)

产生:

【讨论】:

  • @mathematical.cofee:感谢您的精彩回答。一项观察:为什么 LD25、LD50 没有像在基本 R 图中那样触及预测线?任何想法。谢谢
  • @MYaseen208 这与stat_smooth 产生的数字不同,因为它与pi.hat 公式产生的数字不同:尝试绘制第一个p,然后执行lines(x,pi.hat,lty=1,col='red') 以了解我的意思.不幸的是,我对统计数据的了解不足以帮助您(即您的pi.hat 计算是否错误,或者stat_smooth 是否正在执行您不知道的其他计算)。我只能建议查看stat_smooth 的在线帮助,看看它是否提供了有关如何计算平滑器的任何信息。 had.co.nz/ggplot2/stat_smooth.html
  • 虽然我确信调整现有答案是微不足道的,但在当前形式下它并不能回答问题。 IE。由于线段的拐角不在曲线上,因此不会复制该图。
  • @MYaseen208 这是因为 stat_smooth 没有被传递给你在 glm 调用 mod.fit 时传递的相同选项。特别是,weight 选项未通过。尝试在ggplot 调用中将weight=n 添加到aes
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-08
  • 2014-06-20
  • 1970-01-01
  • 1970-01-01
  • 2020-08-06
  • 2012-02-25
相关资源
最近更新 更多