2015-11-02 17 views
8

Qui è il mio problema (i dati fittizi al fine di essere riproducibile):usare un argomento pesi in un elenco di lm lapply chiama

set.seed(42) 
df<-data.frame("x"=rnorm(1000),"y"=rnorm(1000),"z"=rnorm(1000)) 
df2<-data.frame("x"=rnorm(100),"y"=rnorm(100),"z"=rnorm(100)) 
breaks<-c(-1000,-0.68,-0.01315,0.664,1000) 
divider<-cut(df$x,breaks) 
divider2<-cut(df2$x,breaks) 
subDF<-by(df,INDICES=divider,data.frame) 
subDF2<-by(df2,INDICES=divider2,data.frame) 
reg<-lapply(subDF,lm,formula=x~.) 
pre<-lapply(1:4,function(x){predict(reg[[x]],subDF2[[x]])}) 
lapply(1:4,function(x){summary(reg[[x]])$r.squared}) 

Il codice sopra funziona bene. Quello che sto facendo è il seguente: in base ai valori di x, ho diviso lo df in 4 frame di dati e ho eseguito una regressione su ciascuno di questi dataframes, in modo da poter prevedere i valori per un altro set di dati. La suddivisione del dataframe è per consentire una previsione migliore in quanto l'intervallo di x ha un grande impatto per i dati effettivi.

Quello che sto cercando di fare è aggiungere un argomento di pesi per la regressione per dare maggiore importanza ai dati più recenti. L'argomento I miei pesi è: weights<-0.999^seq(250,1,by=-1) se ci sono 250 dati. Con un seme di 42 e le pause precedenti, tutte le 4 dimensioni sono 250.

Quando provo a fare reg<-lapply(subDF,lm,formula=x~.,weights=0.999^seq(250,1,by=-1)), ho ottenuto questo errore:

Error in eval(expr, envir, enclos) : 
    ..2 used in an incorrect context, no ... to look in 

che è abbastanza strano come lapply ha un ... argomento, usato qui per il formula ma non accetta lo weights.

Quindi davvero non so cosa fare per aggiungere quei pesi. Cosa dovrei correggere nel mio codice o dovrei (quasi) cambiare completamente per poter usare i pesi?

Per l'esempio e per renderlo (forse) più semplice, ho tagliato le interruzioni in modo che i 4 sottoinsiemi abbiano la stessa dimensione ma idealmente la risposta funzionerebbe anche se i 4 sottoinsiemi non hanno la stessa dimensione (quindi per esempio nell'intervallo

This post su CrossValidated ha lo stesso problema, ma senza una soluzione funzionante, quindi non mi ha aiutato.

risposta

3

Non so perché hai ricevuto l'errore che hai ottenuto (ho pensato che lo strumento .... fosse stato creato per questo, ma ho trovato una soluzione leggera, è nella direzione di ciò che ti serve? viene creata una funzione di 'anonymous' all'interno lapply, che calcola i pesi (in base alla dimensione dei dati) e restituisce un modello.

reg2 <- lapply(subDF, function(chunk){ 
    #calculate weights (!dependent on data ordering) 
    weights <- 0.999^seq(nrow(chunk),1,by=-1) 

    #fit model 
    fit <- lm(x~., data=chunk, weights=weights) 
    return(fit) 
}) 
+0

è davvero fantastico! Forse qualcuno saprà qual è il problema ma la tua risposta è quella che stavo cercando – etienne

+1

Prego! Nota che i tuoi pesi correnti sono basati sull'ordine del tuo dataframe. Questo mi rende sempre un po 'nervoso, potrebbe essere più sicuro fare qualcosa come "pesi <- pesi [ordine (dati $ tempo, diminuendo = T)] o simili. – Heroka

6

Purtroppo, avete sperimentato in prima persona la, forse, più brutte errore di R. il errore di non-standard Evaluation (NSE).

Dopo un po 'di scavo nel codice penso di aver trovato il culpr esso. Prendiamo le cose una per una:

Prima di tutto diamo un'occhiata alla traceback():

weights <- 0.999^seq(250,1,by=-1) 

lapply(subDF, lm, formula=x~., weights=weights) 
Error in eval(expr, envir, enclos) : 
    ..2 used in an incorrect context, no ... to look in 
> traceback() 
8: eval(expr, envir, enclos) 
7: eval(extras, data, env) 
6: model.frame.default(formula = ..1, data = X[[1L]], weights = ..2, 
     drop.unused.levels = TRUE) 
5: stats::model.frame(formula = ..1, data = X[[1L]], weights = ..2, 
     drop.unused.levels = TRUE) 
4: eval(expr, envir, enclos) 
3: eval(mf, parent.frame()) 
2: FUN(X[[1L]], ...) 
1: lapply(subDF, lm, formula = x ~ ., weights = weights) 

Sembra che il problema si verifica all'interno del model.frame.default. Quindi, diamo un'occhiata al codice sorgente. Non voglio pubblicare il codice sorgente insieme, ma se si digita model.frame.default nella console, si vedrà qualche parte nel mezzo:

extras <- substitute(list(...)) 
extranames <- names(extras[-1L]) 
extras <- eval(extras, data, env) 

L'ultima riga è dove fallisce. La prima riga è ciò che viene chiamato NSE e viene creata da substitute. substitute creerà quello che viene chiamato expression, diciamo qualcosa come un oggetto da valutare (ad es.creato) più avanti all'interno di eval. Come si può vedere in eval, extras sarà valutato in data e quindi se non trovato in env. Per la formula è ok perché viene valutata nei dati e indicherà eval per utilizzare tutte le colonne in data. weights sebbene non sia nello data. Pertanto, eval lo cercherà in env. Ma cos'è env?

A quanto pare, env è un ambiente e viene creato nel model.frame.default nella linea:

env <- environment(formula$terms) 

Allora, che cosa significa? Vediamo un altro esempio:

xtest <- function(x) { 
    new_func <- function(x) { 
    env <- environment(x) 
    print(env) 
    } 
    new_func(x) 
} 

> xtest(x~z) 
<environment: R_GlobalEnv> 

Nella funzione di cui sopra cerco di replicarsi in un minor numero di linee di quello che sarà in envmodel.frame.default. Come puoi vedere, environment(formula) indica l'ambiente globale.

Quindi, è lì dove env cerca di trovare ..2 vale a dire il secondo argomento passato a ... (vale a dire weights), ma in quanto non v'è alcun ... nel contesto globale, si ha un errore. Spero sia chiaro ora!

soluzione migliore e quello che vorrei fare è utilizzare la risposta @Heroka s' per risolverlo (o si potrebbe riscrivere l'intera model.frame.default e lm da zero senza utilizzare NSE ma penso che il primo è più ragionevole :)).

+0

è fantastico grazie! Ho anche provato a fare 'w <-0.99^seq (1000,1, per = -1) df <-cbind (df, w)' per avere i pesi nei dati ma non riesce ancora. Dato che i pesi sono ora nei dati, sai perché? – etienne

+0

Come è la chiamata "lapply" allora? – LyzandeR

+0

'lapply (subDF, lm, formula = x ~ y + z, weights = w)' – etienne

Problemi correlati