Công thức với số biến động


82

Giả sử, có một số foo_data_frame data.frame và người ta muốn tìm hồi quy của cột mục tiêu Y theo một số cột khác. Vì mục đích đó, một số công thức và mô hình thường được sử dụng. Ví dụ:

linear_model <- lm(Y ~ FACTOR_NAME_1 + FACTOR_NAME_2, foo_data_frame)

Điều đó hoạt động tốt nếu công thức được mã hóa tĩnh. Nếu muốn root trên một số mô hình với số lượng biến phụ thuộc không đổi (giả sử, 2) thì nó có thể được xử lý như vậy:

for (i in seq_len(factor_number)) {
  for (j in seq(i + 1, factor_number)) {
    linear_model <- lm(Y ~ F1 + F2, list(Y=foo_data_frame$Y,
                                         F1=foo_data_frame[[i]],
                                         F2=foo_data_frame[[j]]))
    # linear_model further analyzing...
  }
}

Câu hỏi của tôi là làm thế nào để làm điều tương tự ảnh hưởng khi số lượng biến đang thay đổi động trong quá trình chạy chương trình?

for (number_of_factors in seq_len(5)) {
   # Then root over subsets with #number_of_factors cardinality.
   for (factors_subset in all_subsets_with_fixed_cardinality) {
     # Here I want to fit model with factors from factors_subset.
     linear_model <- lm(Does R provide smth to write here?)
   }
}

2
Cảm ơn! ví dụ ở giữa của bạn khiến tôi nhận ra rằng tôi không cần giải pháp cho câu hỏi của bạn và có thể làm điều gì đó đơn giản hơn nhiều!
Mark Adamson

Câu trả lời:


103

Xem ?as.formula, ví dụ:

factors <- c("factor1", "factor2")
as.formula(paste("y~", paste(factors, collapse="+")))
# y ~ factor1 + factor2

đâu factorslà một vectơ ký tự chứa tên của các yếu tố bạn muốn sử dụng trong mô hình. Điều này bạn có thể dán vào một lmmô hình, ví dụ:

set.seed(0)
y <- rnorm(100)
factor1 <- rep(1:2, each=50)
factor2 <- rep(3:4, 50)
lm(as.formula(paste("y~", paste(factors, collapse="+"))))

# Call:
# lm(formula = as.formula(paste("y~", paste(factors, collapse = "+"))))

# Coefficients:
# (Intercept)      factor1      factor2  
#    0.542471    -0.002525    -0.147433

66

Một chức năng bị lãng quên là reformulate. Từ ?reformulate:

reformulate tạo một công thức từ một vectơ ký tự.


Một ví dụ đơn giản:

listoffactors <- c("factor1","factor2")
reformulate(termlabels = listoffactors, response = 'y')

sẽ mang lại công thức này:

y ~ factor1 + factor2


Mặc dù không được ghi lại rõ ràng, bạn cũng có thể thêm các điều khoản tương tác:

listofintfactors <- c("(factor3","factor4)^2")
reformulate(termlabels = c(listoffactors, listofintfactors), 
    response = 'y')

sẽ mang lại:

y ~ factor1 + factor2 + (factor3 + factor4)^2


3
@JorisMeys Và nó đẹp hơn rất nhiều vì nó cho phép thêm các điều khoản tương tác! Tôi đã tìm kiếm một giải pháp tương tự trong nhiều năm ..
landroni

Điều gì sẽ xảy ra nếu các biến x chứa khoảng trắng? Say "yếu tố 1", "yếu tố 2" vv ..
tiên đề

11

Một tùy chọn khác có thể là sử dụng ma trận trong công thức:

Y = rnorm(10)
foo = matrix(rnorm(100),10,10)
factors=c(1,5,8)

lm(Y ~ foo[,factors])

3
+1, nhưng hãy lưu ý thực tế là điều này không cho phép sử dụng các hiệu ứng tương tác. Cho rằng người ta có thể xây dựng một ma trận mô hình cũng (xem ?model.matrix)
Joris meys

4

Bạn thực sự không cần một công thức. Những công việc này:

lm(data_frame[c("Y", "factor1", "factor2")])

như thế này:

v <- c("Y", "factor1", "factor2")
do.call("lm", list(bquote(data_frame[.(v)])))

+1 Rất đúng, nhưng một lần nữa, bạn phải sử dụng model.matrix để xây dựng ma trận với các hiệu ứng tương tác.
Joris Meys

0

Tôi thường giải quyết vấn đề này bằng cách thay đổi tên của cột phản hồi của mình. Nó dễ dàng hơn để thực hiện động và có thể sạch hơn.

model_response <- "response_field_name"
setnames(model_data_train, c(model_response), "response") #if using data.table
model_gbm <- gbm(response ~ ., data=model_data_train, ...)
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.