Como obter os valores usados ​​em plot.gam em mgcv?

9

Gostaria de descobrir os valores (x, y)usados ​​na plotagem plot(b, seWithMean=TRUE)no pacote mgcv . Alguém sabe como posso extrair ou calcular esses valores?

Aqui está um exemplo:

library(mgcv) 
set.seed(0)
dat <- gamSim(1, n=400, dist="normal", scale=2) 
b   <- gam(y~s(x0), data=dat) 
plot(b, seWithMean=TRUE)
- Reinstate Monica
fonte
Não conheço gammodelos, mas você examinou os diferentes atributos desse objeto? Você pode ver os nomes dos objetos com names(b). Suponho que os detalhes que você procura serão retidos nesse objeto em algum lugar.
Chase

Respostas:

19

Começando com mgcv1.8-6, plot.gamretorna invisivelmente os dados que usa para gerar os gráficos, ou seja,

pd <- plot(<some gam() model>)

fornece uma lista com os dados da plotagem pd.


RESPOSTA ABAIXO PARA mgcv<= 1.8-5:

Eu amaldiçoei repetidamente o fato de que as funções de plotagem para mgcvnão retornam as coisas que estão plotando - o que se segue é feio, mas funciona:

library(mgcv) 
set.seed(0)
dat <- gamSim(1, n = 400, dist = "normal", scale = 2)
b <- gam(y ~ s(x0) + s(x1) + s(x2) + s(x3), data = dat)

plotData <- list()
trace(mgcv:::plot.gam, at = list(c(27, 1)), 
  ## tested for mgcv_1.8-4. other versions may need different at-argument.
  quote({
    message("ooh, so dirty -- assigning into globalenv()'s plotData...")
    plotData <<- pd
    }))
mgcv::plot.gam(b, seWithMean = TRUE, pages = 1)

par(mfrow = c(2, 2))
for (i in 1:4) {
  plot(plotData[[i]]$x, plotData[[i]]$fit, type = "l", xlim = plotData[[i]]$xlim,
    ylim = range(plotData[[i]]$fit + plotData[[i]]$se, plotData[[i]]$fit -
      plotData[[i]]$se))
  matlines(plotData[[i]]$x, cbind(plotData[[i]]$fit + plotData[[i]]$se, 
    plotData[[i]]$fit - plotData[[i]]$se), lty = 2, col = 1)
  rug(plotData[[i]]$raw)  
}
fabianos
fonte
Muito obrigado pela sua ajuda. Quando reproduzo seu código até plotData <<- c(plotData, pd[[i]])})) , ocorre a seguinte mensagem Error in fBody[[i]] : no such index at level 3. Alguma idéia de por que não funciona?
O truque de "rastreamento" costumava funcionar para mim. No entanto, recentemente me falhou. Eu suspeito que isso tenha a ver com uma nova versão do pacote mgcv (atualmente estou usando a v 1.8-3), que pode exigir um argumento "at" diferente na função de rastreamento. Alguém pode me ajudar em como obter o vetor correto para o argumento "at" da função trace? Muito obrigado antecipadamente!
@Pepijn see my edit.
Fabian
4

O pacote visregpode fazer plotagens de efeito semelhantes ao GAM (mas talvez não sejam idênticas?) E fornece os componentes da plotagem como saída também, formatados como uma lista. Usando o plyr, é possível criar um quadro de dados da saída. Exemplo:

plot <- visreg(model, type = "contrast")
smooths <- ldply(plot, function(part)   
  data.frame(x=part$x$xx, smooth=part$y$fit, lower=part$y$lwr, upper=part$y$upr))
user13380
fonte
3

Esta não será uma resposta completa. Toda a plotagem de gamobjetos está sendo feita com função plot.gam. Você pode ver seu código simplesmente digitando

> plot.gam

no console R. Como você verá, o código é enorme. O que eu deduzi é que toda a plotagem é feita reunindo informações relevantes no pdobjeto que é uma lista. Portanto, uma das soluções possíveis seria editar plot.gam, usando, editpor exemplo, para que ele retorne esse objeto. Adicionar pdantes do último }será suficiente. Eu recomendaria adicionar invisible(pd), para que este objeto seja retornado apenas se você solicitar:

> pd <- plot(b,seWithMean = TRUE)

Em seguida, inspecione esse objeto e pesquise no código plot.gamas linhas com plote lines. Então você verá quais dos valores xe relevantes yaparecem no gráfico.

mpiktas
fonte
Opa, eu não vi o seu quando postei minha resposta. Bem, é um pouco mais detalhada de qualquer maneira ....
fabianos
@fabians, não se preocupe, eu não teria postado o meu se visse o seu. Eu descrevi a idéia geral, você forneceu o código. Como a pergunta pede código, sua resposta é melhor.
Mvctas #
0
## And this is the code for multiple variables!
require(mgcv)
n      = 100
N      = n
tt     = 1:n
arfun  = c(rep(.7,round(n/3)),rep(.3,round(n/3)),rep(-.3,ceiling(n/3)))
arfun2 = c(rep(.8,round(n/3)),rep(.3,round(n/3)),rep(-.3,ceiling(n/3)))
int    = .1*(tt-mean(tt))/max(tt)-.1*((tt-mean(tt))/(max(tt)/10))^2
y      = rep(NA,n)
s.sample <- N
x        <- 10*rnorm(s.sample)
z        <- 10*rnorm(s.sample)
for(j in 1:n){
  y[j]=int[j]+x[j]*arfun[j]+z[j]*arfun2[j]+rnorm(1)  
}

mod = gam(y ~ s(tt) + s(tt, by=x) + s(tt, by=z)) 
## getting the data out of the plot
plotData <- list()
trace(mgcv:::plot.gam, at=list(c(25,3,3,3)),
      # this gets you to the location where plot.gam calls 
      #    plot.mgcv.smooth (see ?trace)
      # plot.mgcv.smooth is the function that does the actual plotting and
      # we simply assign its main argument into the global workspace
      # so we can work with it later.....

      quote({
        # browser()
        print(pd)
        plotData <<- c(plotData, pd)
      }))

# test: 
mgcv::plot.gam(mod, seWithMean=TRUE)


# see if it succeeded
slct = 3
plot(plotData[[slct]]$x, plotData[[slct]]$fit, type="l", xlim=plotData$xlim, 
     ylim=range(plotData[[slct]]$fit + plotData[[slct]]$se, plotData[[slct]]$fit - 
                plotData[[slct]]$se))
matlines(plotData[[slct]]$x, 
         cbind(plotData[[slct]]$fit + plotData[[slct]]$se, 
               plotData[[slct]]$fit - plotData[[slct]]$se), lty=2, col=1)
rug(plotData[[slct]]$raw)
Lauie
fonte