Adattamento di un modello lineare con più LHS

Sono nuovo di R e voglio migliorare il seguente script con una funzione *apply (ho letto su apply , ma non sono riuscito a usarlo). Voglio usare la funzione lm su più variabili indipendenti (che sono colonne in un frame di dati). ero solito

 for (i in (1:3) { assign(paste0('lm.',names(data[i])), lm(formula=formula(i),data=data)) } 

Formula(i) è definita come

 formula=function(x) { as.formula ( paste(names(data[x]),'~', paste0(names(data[-1:-3]), collapse = '+')), env=parent.frame() ) } 

Grazie.

Se non ti sbaglio, stai lavorando con un set di dati come questo:

 set.seed(0) dat < - data.frame(y1 = rnorm(30), y2 = rnorm(30), y3 = rnorm(30), x1 = rnorm(30), x2 = rnorm(30), x3 = rnorm(30)) 

x1 , x2 e x3 sono covariate e y1 , y2 , y3 sono tre risposte indipendenti. Stai provando ad adattare tre modelli lineari:

 y1 ~ x1 + x2 + x3 y2 ~ x1 + x2 + x3 y3 ~ x1 + x2 + x3 

Attualmente stai usando un ciclo attraverso y1 , y2 , y3 , adattando un modello per volta. Speri di accelerare il processo sostituendo il ciclo for con lapply .

Sei sulla strada sbagliata. lm() è un'operazione costosa. Finché il set di dati non è piccolo, i costi del ciclo for sono trascurabili. La sostituzione for loop con lapply non lapply guadagni in termini di prestazioni.

Poiché hai lo stesso RHS (lato destro di ~ ) per tutti e tre i modelli, la matrice del modello è la stessa per tre modelli. Pertanto, la fattorizzazione QR per tutti i modelli deve essere eseguita una sola volta. lm permette questo, e tu puoi usare:

 fit < - lm(cbind(y1, y2, y3) ~ x1 + x2 + x3, data = dat) #Coefficients: # y1 y2 y3 #(Intercept) -0.081155 0.042049 0.007261 #x1 -0.037556 0.181407 -0.070109 #x2 -0.334067 0.223742 0.015100 #x3 0.057861 -0.075975 -0.099762 

Se controlli str(fit) , vedrai che questo non è un elenco di tre modelli lineari; invece, è un singolo modello lineare con un singolo object $qr , ma con più LHS. Quindi $coefficients , $residuals e $fitted.values sono matrici. Il modello lineare risultante ha una class aggiuntiva "mlm" oltre alla solita class "lm". Ho creato un tag mlm speciale raccogliendo alcune domande sul tema, riassunte dal suo tag wiki .

Se disponi di più covariate, puoi evitare di digitare o incollare una formula utilizzando . :

 fit < - lm(cbind(y1, y2, y3) ~ ., data = dat) #Coefficients: # y1 y2 y3 #(Intercept) -0.081155 0.042049 0.007261 #x1 -0.037556 0.181407 -0.070109 #x2 -0.334067 0.223742 0.015100 #x3 0.057861 -0.075975 -0.099762 

Attenzione: non scrivere

 y1 + y2 + y3 ~ x1 + x2 + x3 

Questo tratterà y = y1 + y2 + y3 come una singola risposta. Usa cbind() .


Azione supplementare:

Sono interessato a una generalizzazione. Ho un frame di dati df , dove le prime n colonne sono variabili dipendenti (y1,y2,y3,....) e le successive m colonne sono variabili indipendenti (x1+x2+x3+....) . Per n = 3 e m = 3 è fit < - lm(cbind(y1, y2, y3) ~ ., data = dat)) . Ma come farlo automaticamente, usando la struttura del df . Intendo qualcosa come (for i in (1:n)) fit < - lm(cbind(df[something] ~ df[something], data = dat)) . Quel "qualcosa" l'ho creato con paste e paste0 . Grazie.

Quindi stai programmando la tua formula, o vuoi generare / build dynamicmente le formule del modello nel ciclo. Ci sono molti modi per farlo e molte domande di Stack Overflow riguardano questo. Ci sono comunemente due approcci:

  1. utilizzare reformulate ;
  2. utilizzare paste / paste0 e formula / as.formula .

Preferisco reformulate per la sua accuratezza, tuttavia, non supporta più LHS nella formula. Ha anche bisogno di un trattamento speciale se vuoi trasformare la LHS . Quindi nel seguito vorrei usare la soluzione di paste .

Per te la cornice dati df , puoi farlo

 paste0("cbind(", paste(names(df)[1:n], collapse = ", "), ")", " ~ .") 

Un modo più piacevole è usare sprintf e toString per build il LHS:

 sprintf("cbind(%s) ~ .", toString(names(df)[1:n])) 

Ecco un esempio che utilizza il set di dati iris :

 string_formula < - sprintf("cbind(%s) ~ .", toString(names(iris)[1:2])) # "cbind(Sepal.Length, Sepal.Width) ~ ." 

È ansible passare questa formula di stringa a lm , poiché lm lo costringerà automaticamente in class formula. O puoi fare tu stesso la coercizione usando la formula (o as.formula ):

 formula(string_formula) # cbind(Sepal.Length, Sepal.Width) ~ . 

Osservazioni:

Questa formula LHS multipla è supportata anche altrove in R core:

  • il metodo della formula per l' aggregate funzioni ;
  • Analisi ANOVA con aov .