【问题标题】:R: plotting geom_line() of lm() prediction values and geometric smooth do not coincideR:绘制 lm() 预测值的 geom_line() 和几何平滑不重合
【发布时间】:2020-09-24 23:43:15
【问题描述】:

我有以下数据

df <- data.frame(x= c(0,1,10,100,1000,0,1, 10,100,1000,0,1,10,100,1000), 
                 y=c(7,15,135,1132,6459,-3,11,127,1120,6249,-5,13,126,1208,6208))

在使用数据制作线性模型后,我使用该模型根据已知的 x 值预测 y 值。将预测的 y 值存储在数据框“pred.fits”中

fit <- lm(data = df, y ~ x)

pred.fits <- expand.grid(x=seq(1, 2000, length=2001))

pm <- predict(fit, newdata=pred.fits, interval="confidence")

pred.fits$py <- pm[,1]

我绘制数据并同时使用 geom_smooth() 和 geom_line(),它们似乎很重合。

ggplot(df, aes(x=x, y=y)) + 
       geom_point() + 
       geom_smooth(method = lm, formula = y ~ x, se = FALSE, size=1.5) +
       geom_line(data=pred.fits, aes(x=x, y=py), size=.2)

但是,当我绘制相同的数据时,将坐标轴设置为对数刻度,这两个回归差异很大。

ggplot(df, aes(x=x, y=y)) + 
       geom_point() + 
       geom_smooth(method = lm, formula = y ~ x, se = FALSE, size=1.5) +
       geom_line(data=pred.fits, aes(x=x, y=py), size=.2) + 
       scale_x_log10() + 
       scale_y_log10()

我错过了什么吗?

更新

@Duck 指出我正确的方向后,我能够正确地找到它。问题是,我希望数据未转换,但轴转换为 log10 比例。这就是我能够做到的方式。

df2 <- df[df$x>=1,] # remove annoying warning msgs.

fit2 <- lm(data = df2, log10(y) ~ log10(x))

pred.fits2 <- expand.grid(x=seq(10^0, 10^3  , length=200))

pm2 <- predict(fit2, newdata=pred.fits2, interval="confidence")

pred.fits2$py <-  10^pm2[,1] # convert the predicted y values to linear scale

ggplot(df2, aes(x=x, y=y)) + 
geom_point() + 
geom_smooth(method = lm, formula = y ~ x, se = FALSE, size=1.5) +
geom_line(data=pred.fits2, aes(x=x, y=py), size=1.5, linetype = "longdash") + 
scale_x_log10() +
scale_y_log10()

感谢大家的帮助。

【问题讨论】:

  • 检查这个答案,在你的数据中也有可能影响平滑计算的负值和零stackoverflow.com/questions/29275288/…
  • 添加到@Duck 所说的内容(完全正确,负数和 0 是问题)-您也不会得到相同的结果,因为在第二个图中,您正在估计对数转换数据的回归并绘制线性回归到对数空间的结果,它们不相等。如果是这样,我们将简单地运行回归并记录转换结果。

标签: r ggplot2 lm


【解决方案1】:

此代码有助于您理解(感谢@BWilliams 的宝贵评论)。您希望 x 和 y 采用对数比例,因此如果将线性模型与不同比例混合可能会搞砸一切。如果您想查看相似的比例,最好使用对数变量训练不同的模型,然后使用正确的值对其进行绘制。这是一种我们构建对数对数模型然后绘图的方法(数据值为 1 或负数已被隔离在新的数据框 df2 中)。代码如下:

第一个线性模型:

library(ggplot2)
#Data
df <- data.frame(x= c(0,1,10,100,1000,0,1, 10,100,1000,0,1,10,100,1000), 
                 y=c(7,15,135,1132,6459,-3,11,127,1120,6249,-5,13,126,1208,6208))

#Model 1 all obs
fit <- lm(data = df, y ~ x)
pred.fits <- expand.grid(x=seq(1, 2000, length=2001))
pm <- predict(fit, newdata=pred.fits, interval="confidence")
pred.fits$py <- pm[,1]
#Plot 1
ggplot(df, aes(x=x, y=y)) + 
  geom_point() + 
  geom_smooth(method = lm, formula = y ~ x, se = FALSE, size=1.5) +
  geom_line(data=pred.fits, aes(x=x, y=py), size=.2)

输出:

现在是日志变量的草图,请注意我们如何在主要变量中使用log(),以及如何构建模型:

#First remove issue values
df2 <- df[df$x>1,]
#Train a new model
pred.fits2 <- expand.grid(x=seq(1, 2000, length=2001))
fit2 <- lm(data = df2, log(y) ~ log(x))
pm2 <- predict(fit2, newdata=pred.fits2, interval="confidence")
pred.fits2$py <- pm2[,1]
#Plot 2
ggplot(df2, aes(x=log(x), y=log(y))) + 
  geom_point() + 
  geom_smooth(method = lm, formula = y ~ x, se = FALSE, size=1.5) +
  geom_line(data=pred.fits2, aes(x=log(x), y=py), size=.2)

输出:

【讨论】:

  • @Duck,感谢您快速清晰的解释。因此 geom_smooth() 函数可以感知轴从线性变为对数,并使用 lm() 在 log10(x) ~ log10(y) 公式上生成回归线,而 geom_line() 错过了它,因为它已经完成超出 ggplot() 调用。
  • @Deb.M 是的,首先尝试使用帖子中看到的模型和转换进行测试。 ggplot2 中的某些功能以不同的方式管理转换,因此您可能会在尝试复制从您的角度来看非常合乎逻辑的东西时遇到麻烦。希望对你有所帮助:)
  • 你的回答让我看到了曙光,所以这绝对是有帮助的:)。还有一个相关的问题。有没有办法将轴保持为 0,1,10,100... 而不是 0,1,2,3... 就像在日志纸上绘制图表一样?
  • @Deb.M 我建议你使用scale_x_continuous()scale_y_continuous()。这些函数具有标签、限制和中断选项,以便您可以自定义轴。我希望这会有所帮助:)
  • @Deb.M 如果需要更多帮助,请告诉我。有时我可能不清楚!
猜你喜欢
  • 2018-11-08
  • 2014-10-11
  • 1970-01-01
  • 1970-01-01
  • 2018-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多