Come scrivere succintamente una formula con molte variabili da un frame di dati?


127

Supponiamo di avere una variabile di risposta e un dato contenente tre covariate (come un esempio di giocattolo):

y = c(1,4,6)
d = data.frame(x1 = c(4,-1,3), x2 = c(3,9,8), x3 = c(4,-4,-2))

Voglio adattare una regressione lineare ai dati:

fit = lm(y ~ d$x1 + d$x2 + d$y2)

C'è un modo per scrivere la formula, in modo da non dover scrivere ogni singola covariata? Ad esempio, qualcosa di simile

fit = lm(y ~ d)

(Voglio che ogni variabile nel data frame sia una covariata.) Chiedo perché in realtà ho 50 variabili nel mio data frame, quindi voglio evitare di scrivere x1 + x2 + x3 + etc.



Risposte:


202

C'è un identificatore speciale che si può usare in una formula per indicare tutte le variabili, è l' .identificatore.

y <- c(1,4,6)
d <- data.frame(y = y, x1 = c(4,-1,3), x2 = c(3,9,8), x3 = c(4,-4,-2))
mod <- lm(y ~ ., data = d)

Puoi anche fare cose come questa, per usare tutte le variabili tranne una (in questo caso x3 è escluso):

mod <- lm(y ~ . - x3, data = d)

Tecnicamente, .significa tutte le variabili non già menzionate nella formula . Per esempio

lm(y ~ x1 * x2 + ., data = d)

dove .farebbe riferimento solo x3come x1e x2sono già nella formula.


Il data frame "d" ha 4 colonne (y, x1, x2 e x3). Quindi, se la formula è "y ~.", Il lato destro significa "tutte le colonne" tranne quelle elencate sul lato sinistro?
stackoverflowuser2010

1
@ stackoverflowuser2010 Sì, .tecnicamente significa che tutte le variabili data non sono già presenti nella formula .
Gavin Simpson

1
@theforestecologist se intendi che dataè un elenco da cui le variabili nella formula vengono cercate da quell'elenco , allora sì. Un data frame, un elenco o un ambiente sono opzioni accettabili per l' dataargomento. Se non è questo ciò che intendi, dovrai espandere un po 'di più.
Gavin Simpson

@Gavin. Questo è ciò che intendevo. Grazie. Come dovrei utilizzare questo metodo utilizzando i dati [[x]] come variabile elencata rispetto al nome effettivo della variabile (ad esempio, "x3")? Ad esempio, come potrei fare il seguente lavoro?:lm(d[[1]] ~ d[[3]] + ., data = d)
theforestecologist

Funziona fuori namesdalla lista; dire che avete ll <- list(y = rnorm(10), x = rnorm(10), z = rnorm(10), zz = runif(10)), allora le seguenti opere: lm(y ~ x + ., data = ll). Quindi non c'è motivo di avere i tuoi dati in questo modo a meno che non sia già un elenco, ma funziona. Il requisito che gli elementi della formula abbiano la stessa lunghezza pone alcune restrizioni su ciò che hai in un elenco. Oggetti più complessi probabilmente necessitano di codice per estrarre gli elementi desiderati; se d[[1]]fosse un data frame / matrice hai bisogno del codice per farlo funzionare
Gavin Simpson

66

Un approccio leggermente diverso consiste nel creare la formula da una stringa. Nella formulapagina della guida troverai il seguente esempio:

## Create a formula for a model with a large number of variables:
xnam <- paste("x", 1:25, sep="")
fmla <- as.formula(paste("y ~ ", paste(xnam, collapse= "+")))

Quindi se guardi la formula generata, otterrai:

R> fmla
y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + 
    x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20 + x21 + 
    x22 + x23 + x24 + x25

1
Funziona molto bene per leggere questi valori da un file. Grazie!
Ben Sidhom

Nota che la parte as.formula è d'obbligo
Jinhua Wang

7

Sì, certo, aggiungi la risposta ycome prima colonna nel dataframe e chiamala lm():

d2<-data.frame(y,d)
> d2
  y x1 x2 x3
1 1  4  3  4
2 4 -1  9 -4
3 6  3  8 -2
> lm(d2)

Call:
lm(formula = d2)

Coefficients:
(Intercept)           x1           x2           x3  
    -5.6316       0.7895       1.1579           NA  

Inoltre, le mie informazioni su R indicano che l'assegnazione con <-è consigliata =.


Grazie! Sì, so che tutti dicono sempre di usare <-, ma nessuno dice mai perché e = è più facile da digitare =).
grautur

2
@gratur Una ragione è che cose come foo(bar <- 1:10)funzionano (e barvengono create) ma foo(bar = 1:10)fallirebbero perché barnon sono un argomento fooe non creeranno barneanche.
Gavin Simpson

2
Perché il coefficiente di x3 NA?
ziyuang

6

Un'estensione del metodo di juba consiste nell'usare reformulate, una funzione che è espressamente progettata per tale compito.

## Create a formula for a model with a large number of variables:
xnam <- paste("x", 1:25, sep="")

reformulate(xnam, "y")
y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + 
    x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20 + x21 + 
    x22 + x23 + x24 + x25

Per l'esempio nell'OP, la soluzione più semplice qui sarebbe

# add y variable to data.frame d
d <- cbind(y, d)
reformulate(names(d)[-1], names(d[1]))
y ~ x1 + x2 + x3

o

mod <- lm(reformulate(names(d)[-1], names(d[1])), data=d)

Si noti che l'aggiunta della variabile dipendente a data.frame in d <- cbind(y, d)è preferibile non solo perché consente l'uso di reformulate, ma anche perché consente l'uso futuro lmdell'oggetto in funzioni come predict.


2

Costruisco questa soluzione, reformulatenon mi interessa se i nomi delle variabili hanno spazi bianchi.

add_backticks = function(x) {
    paste0("`", x, "`")
}

x_lm_formula = function(x) {
    paste(add_backticks(x), collapse = " + ")
}

build_lm_formula = function(x, y){
    if (length(y)>1){
        stop("y needs to be just one variable")
    }
    as.formula(        
        paste0("`",y,"`", " ~ ", x_lm_formula(x))
    )
}

# Example
df <- data.frame(
    y = c(1,4,6), 
    x1 = c(4,-1,3), 
    x2 = c(3,9,8), 
    x3 = c(4,-4,-2)
    )

# Model Specification
columns = colnames(df)
y_cols = columns[1]
x_cols = columns[2:length(columns)]
formula = build_lm_formula(x_cols, y_cols)
formula
# output
# "`y` ~ `x1` + `x2` + `x3`"

# Run Model
lm(formula = formula, data = df)
# output
Call:
    lm(formula = formula, data = df)

Coefficients:
    (Intercept)           x1           x2           x3  
        -5.6316       0.7895       1.1579           NA  

`` `


0

È possibile controllare il pacchetto leapse in particolare le funzioni regsubsets() funzionali per la selezione del modello. Come indicato nella documentazione:

Selezione del modello tramite ricerca esaustiva, sostituzione graduale in avanti o indietro o sostituzione sequenziale

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.