Come ottenere i valori usati in plot.gam in mgcv?


10

Vorrei scoprire i valori (x, y)usati nella stampa plot(b, seWithMean=TRUE)nel pacchetto mgcv . Qualcuno sa come posso estrarre o calcolare questi valori?

Ecco un esempio:

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)

Non ho familiarità con i gammodelli, ma hai esaminato i diversi attributi di quell'oggetto? Puoi guardare i nomi degli oggetti con names(b). Immagino che qualsiasi dettaglio tu stia cercando sarà conservato all'interno di quell'oggetto da qualche parte.
Chase

Risposte:


19

A partire da mgcv1,8-6, plot.gamrestituisce in modo invisibile i dati che utilizza per generare i grafici, ovvero facendo

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

ti dà un elenco con i dati di stampa in pd.


RISPOSTA SOTTO PER mgcv<= 1.8-5:

Ho ripetutamente maledetto il fatto che la trama funzioni per mgcvnon restituire le cose che stanno tramando - ciò che segue è brutto ma funziona:

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)  
}

Molte grazie per il vostro aiuto. Quando riproduco il codice fino a plotData <<- c(plotData, pd[[i]])})) , viene visualizzato il seguente messaggio Error in fBody[[i]] : no such index at level 3. Qualche idea sul perché non funzioni?

Il trucco "traccia" funzionava per me. Tuttavia, recentemente mi ha deluso. Sospetto che abbia a che fare con una nuova versione del pacchetto mgcv (sto attualmente usando la v 1.8-3), che potrebbe richiedere un argomento "at" diverso nella funzione trace. Qualcuno può aiutarmi su come ottenere il vettore corretto per l'argomento "at" della funzione trace? Molte grazie in anticipo!

@Pepijn guarda la mia modifica.
fabians

4

Il pacchetto visregpuò rendere grafici di effetti simili a GAM (ma forse non identici?) E fornisce anche i componenti del diagramma come output, formattati come un elenco. Usando plyr si può creare un frame di dati dell'output. Esempio:

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))

3

Questa non sarà una risposta completa. Tutte le trame per gli gamoggetti vengono eseguite con la funzione plot.gam. Puoi guardare il suo codice semplicemente digitando

> plot.gam

nella console R. Come vedrai il codice è enorme. Ciò che ho ricavato da ciò è che tutte le trame vengono eseguite raccogliendo informazioni rilevanti pdnell'oggetto che è un elenco. Quindi una delle possibili soluzioni sarebbe quella di modificare plot.gam, usando editad esempio, in modo che restituisca quell'oggetto. L'aggiunta pdprima dell'ultima }sarà sufficiente. Suggerirei di aggiungere invisible(pd), in modo che questo oggetto venga restituito solo se lo chiedi:

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

Quindi ispeziona questo oggetto e cerca nel codice di plot.gamle righe con plote lines. Quindi vedrai quali dei pertinenti xe dei yvalori compaiono nella trama.


oops, non ho visto il tuo quando ho pubblicato la mia risposta. Bene, è comunque un po 'più dettagliato ....
fabians

@fabians, non preoccuparti, non avrei pubblicato il mio se avessi visto il tuo. Ho delineato l'idea generale, hai fornito il codice. Poiché la domanda richiede il codice, la tua risposta è migliore.
mpiktas,

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.