Làm thế nào để viết một công thức có nhiều biến từ một khung dữ liệu?


127

Giả sử tôi có một biến phản hồi và một dữ liệu chứa ba biến số (như một ví dụ đồ chơi):

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

Tôi muốn phù hợp với một hồi quy tuyến tính với dữ liệu:

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

Có cách nào để viết công thức để tôi không phải viết ra từng hiệp biến riêng lẻ không? Ví dụ, một cái gì đó như

fit = lm(y ~ d)

(Tôi muốn mỗi biến trong khung dữ liệu là một hiệp biến.) Tôi đang hỏi vì tôi thực sự có 50 biến trong khung dữ liệu của mình, vì vậy tôi muốn tránh viết ra x1 + x2 + x3 + etc.



Câu trả lời:


202

Có một định danh đặc biệt mà người ta có thể sử dụng trong công thức để có nghĩa là tất cả các biến, đó là .định danh.

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)

Bạn cũng có thể làm những việc như thế này, để sử dụng tất cả các biến trừ một biến (trong trường hợp này x3 bị loại trừ):

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

Về mặt kỹ thuật, .có nghĩa là tất cả các biến chưa được đề cập trong công thức . Ví dụ

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

nơi .sẽ chỉ tham chiếu x3như x1x2đã có trong công thức.


Khung dữ liệu 'd' có 4 cột (y, x1, x2 và x3). Vậy nếu công thức là "y ~.", Thì bên tay phải có nghĩa là "tất cả các cột" ngoại trừ những cột được liệt kê ở bên tay trái không?
stackoverflowuser2010

1
@ stackoverflowuser2010 Có, .về mặt kỹ thuật có nghĩa là tất cả các biến data chưa có trong công thức .
Gavin Simpson

1
@theforestecologist nếu bạn muốn nói datalà một danh sách mà từ đó các biến trong công thức được tra cứu từ danh sách đó, thì có. Khung dữ liệu, danh sách hoặc môi trường là những tùy chọn được chấp nhận cho datađối số. Nếu đó không phải là ý bạn, bạn sẽ cần mở rộng thêm một chút.
Gavin Simpson

@Gavin. Đó là những gì tôi muốn nói. Cảm ơn. Tôi sẽ làm thế nào về phương pháp này bằng cách sử dụng dữ liệu [[x]] như một biến được liệt kê so với tên biến thực tế (ví dụ: 'x3')? Ví dụ, làm thế nào tôi sẽ làm cho công việc sau đây ?:lm(d[[1]] ~ d[[3]] + ., data = d)
theforestecologist

Nó hoạt động ngoài namesdanh sách; nói rằng bạn có ll <- list(y = rnorm(10), x = rnorm(10), z = rnorm(10), zz = runif(10)), sau đó các công việc sau: lm(y ~ x + ., data = ll). Vì vậy, không có nhiều lý do để có dữ liệu của bạn như thế này trừ khi nó đã là một danh sách, nhưng nó hoạt động. Yêu cầu rằng các phần tử của công thức có cùng độ dài đặt ra một số hạn chế đối với những gì bạn có trong danh sách. Các đối tượng phức tạp hơn có thể cần mã để trích xuất các phần tử bạn muốn; nếu d[[1]]là một khung / ma trận dữ liệu, bạn cần mã để làm cho nó hoạt động
Gavin Simpson

66

Một cách tiếp cận hơi khác là tạo công thức của bạn từ một chuỗi. Trong formulatrang trợ giúp, bạn sẽ tìm thấy ví dụ sau:

## 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= "+")))

Sau đó, nếu bạn nhìn vào công thức đã tạo, bạn sẽ nhận được:

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
Điều này hoạt động rất tốt để đọc các giá trị này từ một tệp. Cảm ơn!
Ben Sidhom

Lưu ý rằng phần as.formula là một mustt
Kim Hoa Wang

7

Tất nhiên là có, chỉ cần thêm phản hồi ylàm cột đầu tiên trong khung dữ liệu và gọi lm()nó:

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  

Ngoài ra, thông tin của tôi về R chỉ ra rằng việc chuyển nhượng với <-được khuyến nghị kết thúc =.


Cảm ơn! Vâng, tôi biết mọi người luôn nói sử dụng <-, nhưng không ai nói tại sao và = dễ nhập hơn =).
grautur

2
@gratur Một lý do là những thứ như foo(bar <- 1:10)công việc (và barđược tạo ra) nhưng foo(bar = 1:10)sẽ thất bại vì barkhông phải là đối số của foovà cũng sẽ không tạo ra bar.
Gavin Simpson

2
Tại sao lại là hệ số của x3 NA?
ziyuang

6

Một phần mở rộng của phương pháp juba là sử dụng reformulate, một hàm được thiết kế rõ ràng cho một nhiệm vụ như vậy.

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

Đối với ví dụ trong OP, giải pháp đơn giản nhất ở đây sẽ là

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

hoặc là

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

Lưu ý rằng việc thêm biến phụ thuộc vào data.frame in d <- cbind(y, d)được ưu tiên không chỉ vì nó cho phép sử dụng reformulatemà còn vì nó cho phép sử dụng lmđối tượng trong các hàm như sau predict.


2

Tôi xây dựng giải pháp này, reformulatekhông quan tâm nếu tên biến có khoảng trắng.

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

Bạn có thể kiểm tra gói leapsvà cụ thể là các chức regsubsets() năng chức năng để lựa chọn mô hình. Như đã nêu trong tài liệu:

Lựa chọn mô hình bằng cách tìm kiếm đầy đủ, tiến hoặc lùi từng bước hoặc thay thế tuần tự

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.