2012-04-16 14 views
5

Oggi ho realizzato uno strano comportamento con il mio codice R. Ho provato un pacchetto {boot.StepAIC} che include una funzione bootstrap per i risultati della regressione stepwise con AIC. Comunque non credo che lo sfondo statistico sia qui il problema (lo spero).
Posso usare la funzione al livello superiore di R. Questo è il mio codice di esempio.funziona (boot.stepAIC) ma genera un errore all'interno di un'altra funzione: problema di ambiente?

require(MASS) 
require(boot.StepAIC) 

n<-100 
x<-rnorm(n); y<-rnorm(n,sd=2); z<-rnorm(n,sd=3); res<-x+y+z+rnorm(n,sd=0.1) 
dat.test<-as.data.frame(cbind(x,y,z,res)) 
form.1<-as.formula(res~x+y+z) 
boot.stepAIC(lm(form.1, dat.test),dat.test) # should be OK - works at me 

Tuttavia, ho voluto avvolgerlo in una propria funzione. Trasmetto i dati e la formula a quella funzione. Ma ottengo un errore all'interno boot.stepAIC() dicendo:

l'adattamento del modello non è riuscita in 100 campioni di bootstrap Errore in strsplit (nam.vars, ":"): argomento non-personaggio

# custom function 
fun.boot.lm.stepAIC<-function(dat,form) { 
    if(!inherits(form, "formula")) stop("No formula given") 
    fit.lm<-lm(formula=form,data=dat) 
    return(boot.stepAIC(object=fit.lm,data=dat)) 
} 
fun.boot.lm.stepAIC(dat=dat.test,form=form.1) 
# results in an error 

Quindi dov'è l'errore? Suppongo che debba avere qualcosa a che fare con l'ambiente locale e globale, vero?

+0

Non ho usato 'boot.stepAIC' prima, ma il sospetto che può anche avere a che fare con il modo la formula di essere passato alla funzione (che è legato alle questioni ambientali troppo). Vedi http://stackoverflow.com/q/6877534, http://stackoverflow.com/q/7666807 per alcune idee. In particolare, chiamare 'lm' o' boot.stepAIC' tramite 'do.call' può essere d'aiuto nel momento in cui gli argomenti vengono valutati prima di essere passati. Si può anche indagare sul suggerimento' as.name' nei commenti. Questi problemi sono complicati: buona fortuna! – Aaron

+0

http://stackoverflow.com/q/8998884/210673 sembra essere lo stesso problema. – Aaron

+0

sì. Ho già letto questo. Suppongo che i problemi siano collegati. – Sebastian

risposta

4

L'utilizzo di do.call come in anova test fails on lme fits created with pasted formula fornisce la risposta.

non ha accesso a form quando eseguito all'interno di una funzione; che può essere ricreato nell'ambiente globale come questo; vediamo che lm utilizza form.1 come formula e che la sua rimozione non produce l'errore .

> form.1<-as.formula(res~x+y+z) 
> mm <- lm(form.1, dat.test) 
> mm$call 
lm(formula = form.1, data = dat.test) 
> rm(form.1) 
> boot.stepAIC(mm,dat.test) 
# same error as OP 

Utilizzare do.call funziona. Qui uso anche as.name; altrimenti l'oggetto mm porta in giro l'intero set di dati anziché solo il nome di esso.

> form.1<-as.formula(res~x+y+z) 
> mm <- do.call("lm", list(form.1, data=as.name("dat.test"))) 
> mm$call 
lm(formula = res ~ x + y + z, data = dat.test) 
> rm(form.1) 
> boot.stepAIC(mm,dat.test) 

Per applicare questo al problema originale, farei questo:

fun.boot.lm.stepAIC<-function(dat,form) { 
    if(!inherits(form, "formula")) stop("No formula given") 
    mm <- do.call("lm", list(form, data=as.name(dat))) 
    do.call("boot.stepAIC", list(mm,data=as.name(dat))) 
}  
form.1<-as.formula(res~x+y+z) 
fun.boot.lm.stepAIC(dat="dat.test",form=form1) 

questo funziona anche, ma l'intero set di dati verrà incluso nell'oggetto di output finale, e il risultato finale alla console , anche.

fun.boot.lm.stepAIC<-function(dat,form) { 
    if(!inherits(form, "formula")) stop("No formula given") 
    mm <- do.call("lm", list(form, data=dat)) 
    boot.stepAIC(mm,data=dat) 
}  
form.1<-as.formula(res~x+y+z) 
fun.boot.lm.stepAIC(dat=dat.test,form=form.1) 
+0

Grazie. A causa della spiegazione completa, vedo il punto. Ho letto anche i due post correlati. Onestamente, ho ancora mal di testa con questi problemi. Qual è il "caso d'uso" per quel comportamento? Ho passato due oggetti a quella funzione, quindi dovrebbe essere eseguita nel contesto della funzione di chiamata. Non vedo alcun punto in R o nel boot.stepAIC (non so da chi "incolpare") di reindirizzare all'ambiente globale.Il punto è come posso essere certo in quale contesto una funzione sta cercando gli oggetti. La mia comprensione finora è, sempre usare do.call() piuttosto che la funzione direttamente. Qualche strategia su questo? – Sebastian

+0

Beh, ho giocato un po 'con quello e cerco ancora di capire il contesto. Nell'ultimo esempio, in pratica, si passa il nome della variabile globale (o principale) e si accede alla funzione dalla variabile globale dat.test. È una chiamata per riferimento? Potrebbe essere che le funzioni di modellazione a volte utilizzino una chiamata per strategia di riferimento, anche se presumo che sia semplicemente chiamata per valore? – Sebastian

+0

1) 'boot.stepAIC' usa' update', che ripete la chiamata del modello lineare; se la chiamata ha il nome di un oggetto funzione (come 'form'), allora quell'oggetto deve essere accessibile. 2) Ogni funzione ha un ambiente (quello in cui è stato creato, di solito) e una catena di ambienti genitore, che cerca dentro per trovare gli oggetti. Tuttavia, l'esecuzione di una funzione all'interno di un'altra funzione non modifica questa catena principale! Alla fine della catena c'è l'ambiente globale, quindi quando 'form' si trova nell'ambiente globale, può trovarlo. Ma quando 'form' è nell'ambiente della funzione chiamante, non può. – Aaron