r - 是否可以用ggplot2绘制gam拟合的平滑分量?

标签 r ggplot2 gam mgcv

我正在使用 gam 拟合模型来自 mgcv将结果打包并存储在 model到目前为止,我一直在使用 plot(model) 查看平滑组件。 .我最近开始使用 ggplot2 并喜欢它的输出。所以我想知道,是否可以使用 ggplot2 绘制这些图?

下面是一个例子:

x1 = rnorm(1000)
x2 = rnorm(1000)
n = rpois(1000, exp(x1) + x2^2)

model = gam(n ~ s(x1, k=10) + s(x2, k=20), family="poisson")
plot(model, rug=FALSE, select=1)
plot(model, rug=FALSE, select=2)

我对 s(x1, k=10) 感兴趣和 s(x2, k=20)不合身。

部分答案:

我深入挖掘 plot.gammgcv:::plot.mgcv.smooth并构建了我自己的函数,该函数从平滑分量中提取预测效果和标准误差。它不处理 plot.gam 的所有选项和情况。所以我只认为它是部分解决方案,但它对我来说效果很好。
EvaluateSmooths = function(model, select=NULL, x=NULL, n=100) {
  if (is.null(select)) {
    select = 1:length(model$smooth)
  }
  do.call(rbind, lapply(select, function(i) {
    smooth = model$smooth[[i]]
    data = model$model

    if (is.null(x)) {
      min = min(data[smooth$term])
      max = max(data[smooth$term])
      x = seq(min, max, length=n)
    }
    if (smooth$by == "NA") {
      by.level = "NA"
    } else {
      by.level = smooth$by.level
    }
    range = data.frame(x=x, by=by.level)
    names(range) = c(smooth$term, smooth$by)

    mat = PredictMat(smooth, range)
    par = smooth$first.para:smooth$last.para

    y = mat %*% model$coefficients[par]

    se = sqrt(rowSums(
      (mat %*% model$Vp[par, par, drop = FALSE]) * mat
    ))

    return(data.frame(
      label=smooth$label
      , x.var=smooth$term
      , x.val=x
      , by.var=smooth$by
      , by.val=by.level
      , value = y
      , se = se
    ))
  }))
}

这将返回一个带有平滑组件的“熔化”数据框,因此现在可以使用 ggplot上面的例子:
smooths = EvaluateSmooths(model)

ggplot(smooths, aes(x.val, value)) + 
  geom_line() + 
  geom_line(aes(y=value + 2*se), linetype="dashed") + 
  geom_line(aes(y=value - 2*se), linetype="dashed") + 
  facet_grid(. ~ x.var)

如果有人知道在一般情况下允许这样做的软件包,我将不胜感激。

最佳答案

您可以将 visreg 包与 plyr 包结合使用。 visreg 基本上绘制了您可以使用 predict() 的任何模型。

library(mgcv)
library(visreg)
library(plyr)
library(ggplot2)

# Estimating gam model:
x1 = rnorm(1000)
x2 = rnorm(1000)
n = rpois(1000, exp(x1) + x2^2)
model = gam(n ~ s(x1, k=10) + s(x2, k=20), family="poisson")

# use plot = FALSE to get plot data from visreg without plotting
plotdata <- visreg(model, type = "contrast", plot = FALSE)

# The output from visreg is a list of the same length as the number of 'x' variables,
#   so we use ldply to pick the objects we want from the each list part and make a dataframe: 
smooths <- ldply(plotdata, function(part)   
  data.frame(Variable = part$meta$x, 
             x=part$fit[[part$meta$x]], 
             smooth=part$fit$visregFit, 
             lower=part$fit$visregLwr, 
             upper=part$fit$visregUpr))

# The ggplot:
ggplot(smooths, aes(x, smooth)) + geom_line() +
  geom_line(aes(y=lower), linetype="dashed") + 
  geom_line(aes(y=upper), linetype="dashed") + 
  facet_grid(. ~ Variable, scales = "free_x")

我们可以将整个事物放入一个函数中,并添加一个选项来显示模型中的残差(res = TRUE):
ggplot.model <- function(model, type="conditional", res=FALSE, 
                       col.line="#7fc97f", col.point="#beaed4", size.line=1, size.point=1) {
  require(visreg)
  require(plyr)
  plotdata <- visreg(model, type = type, plot = FALSE)
  smooths <- ldply(plotdata, function(part)   
    data.frame(Variable = part$meta$x, 
             x=part$fit[[part$meta$x]], 
             smooth=part$fit$visregFit, 
             lower=part$fit$visregLwr, 
             upper=part$fit$visregUpr))
  residuals <- ldply(plotdata, function(part)
    data.frame(Variable = part$meta$x, 
               x=part$res[[part$meta$x]], 
               y=part$res$visregRes))
  if (res)
    ggplot(smooths, aes(x, smooth)) + geom_line(col=col.line, size=size.line) +
      geom_line(aes(y=lower), linetype="dashed", col=col.line, size=size.line) +
      geom_line(aes(y=upper), linetype="dashed", col=col.line, size=size.line) +
      geom_point(data = residuals, aes(x, y), col=col.point, size=size.point) +
      facet_grid(. ~ Variable, scales = "free_x")
  else
    ggplot(smooths, aes(x, smooth)) + geom_line(col=col.line, size=size.line) +
      geom_line(aes(y=lower), linetype="dashed", col=col.line, size=size.line) +
      geom_line(aes(y=upper), linetype="dashed", col=col.line, size=size.line) +
      facet_grid(. ~ Variable, scales = "free_x")
  }

ggplot.model(model)
ggplot.model(model, res=TRUE)

ggplot without residuals
ggplot with residuals
颜色取自 http://colorbrewer2.org/ .

关于r - 是否可以用ggplot2绘制gam拟合的平滑分量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19735149/

相关文章:

r - 计算 R 中 col1 中每个不同值的 col2 中不同值的数量

r - 将 Mathematica 方程转换为 R 代码

R - 识别数据框列中的常见元素

r - 在 Shiny 应用程序中创建动态选项卡集会在 ggploty 上出现错误

r - 广义加性模型 (GAM) 中的自相关

r - 使用 bam 的零膨胀模型 (ziP) 中的错误

r - 是否可以在 mgcv gam 模型中包含两个平滑项的乘积

r - 如何将数据仅连接到 R 中带有 {data.table} 的第一个匹配行

R ggplot分组并绘制多条线

r - 小块饼图上的标签(ggplot)