วิธีการเขียนสูตรอย่างรวบรัดโดยมีตัวแปรหลายตัวจาก data frame?


127

สมมติว่าฉันมีตัวแปรการตอบสนองและข้อมูลที่มีสามตัวแปรร่วม (เป็นตัวอย่างของเล่น):

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

ฉันต้องการปรับการถดถอยเชิงเส้นให้พอดีกับข้อมูล:

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

มีวิธีเขียนสูตรไหมโดยที่ฉันไม่ต้องเขียนความแปรปรวนร่วมแต่ละตัว ตัวอย่างเช่น

fit = lm(y ~ d)

(ฉันต้องการให้แต่ละตัวแปรใน data frame เป็นตัวแปรร่วม) ฉันถามเพราะจริงๆแล้วฉันมีตัวแปร 50 ตัวใน data frame ของฉันดังนั้นฉันจึงต้องการหลีกเลี่ยงการเขียนออกx1 + x2 + x3 + etcไป



1
lmo

คำตอบ:


202

มีตัวระบุพิเศษที่สามารถใช้ในสูตรเพื่อหมายถึงตัวแปรทั้งหมดนั่นคือ.ตัวระบุ

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)

คุณสามารถทำสิ่งนี้ได้เช่นกันเพื่อใช้ตัวแปรทั้งหมดยกเว้นตัวแปรเดียว (ในกรณีนี้จะไม่รวม x3):

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

เทคนิค.หมายถึงตัวแปรทั้งหมดไม่ได้กล่าวถึงแล้วในสูตร ตัวอย่างเช่น

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

ที่.จะอ้างอิงx3เป็นx1และx2มีอยู่แล้วในสูตร


กรอบข้อมูล 'd' มี 4 คอลัมน์ (y, x1, x2 และ x3) ดังนั้นถ้าสูตรเป็น "y ~" ทางขวามือจะหมายถึง "คอลัมน์ทั้งหมด" ยกเว้นที่ระบุไว้ทางด้านซ้ายมือหรือไม่?
stackoverflowuser2010

1
@ stackoverflowuser2010 ใช่.ในทางเทคนิคหมายถึงตัวแปรทั้งหมดในไม่ได้อยู่ในสูตรdata
Gavin Simpson

1
@theforestecologist ถ้าคุณหมายถึงdataรายการที่ค้นหาตัวแปรในสูตรจากรายการนั้นใช่ กรอบข้อมูลรายการหรือสภาพแวดล้อมเป็นตัวเลือกที่ยอมรับได้สำหรับdataอาร์กิวเมนต์ หากนั่นไม่ใช่สิ่งที่คุณหมายถึงคุณจะต้องขยายความอีกเล็กน้อย
Gavin Simpson

@Gavin นั่นคือสิ่งที่ฉันหมายถึง ขอบคุณ ฉันจะใช้วิธีนี้อย่างไรโดยใช้ data [[x]] เป็นตัวแปรในรายการเทียบกับชื่อตัวแปรจริง (เช่น 'x3') ตัวอย่างเช่นฉันจะทำงานต่อไปนี้ได้อย่างไร:lm(d[[1]] ~ d[[3]] + ., data = d)
theforestecologist

มันทำงานนอกnamesรายการ พูดว่าคุณมีll <- list(y = rnorm(10), x = rnorm(10), z = rnorm(10), zz = runif(10))แล้วงานต่อไปนี้: lm(y ~ x + ., data = ll). ดังนั้นจึงไม่มีเหตุผลมากนักที่จะทำให้ข้อมูลของคุณมีลักษณะเช่นนี้เว้นแต่จะเป็นรายการอยู่แล้ว แต่ใช้งานได้ ข้อกำหนดที่ให้องค์ประกอบของสูตรมีความยาวเท่ากันทำให้มีข้อ จำกัด บางประการเกี่ยวกับสิ่งที่คุณมีในรายการ วัตถุที่ซับซ้อนมากขึ้นอาจต้องใช้รหัสเพื่อแยกองค์ประกอบที่คุณต้องการ หากd[[1]]เป็น data frame / matrix คุณต้องใช้รหัสเพื่อให้ทำงานได้
Gavin Simpson

66

วิธีการที่แตกต่างกันเล็กน้อยคือการสร้างสูตรของคุณจากสตริง ในformulaหน้าวิธีใช้คุณจะพบตัวอย่างต่อไปนี้:

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

จากนั้นหากคุณดูสูตรที่สร้างขึ้นคุณจะได้รับ:

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
ซึ่งใช้งานได้ดีสำหรับการอ่านค่าเหล่านี้จากไฟล์ ขอบคุณ!
Ben Sidhom

โปรดทราบว่าส่วน as.formula เป็นสิ่งที่ต้องทำ
Jinhua Wang

7

ใช่แน่นอนเพียงแค่เพิ่มการตอบกลับyเป็นคอลัมน์แรกในดาต้าเฟรมแล้วเรียก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  

นอกจากนี้ข้อมูลของฉันเกี่ยวกับจุด R ออกที่ได้รับมอบหมายว่าจะแนะนำมากกว่า<-=


ขอบคุณ! ใช่ฉันรู้ว่าทุกคนมักพูดว่าให้ใช้ <- แต่ไม่มีใครเคยบอกว่าทำไมและ = พิมพ์ง่ายกว่า =)
grautur

2
@gratur เหตุผลประการหนึ่งคือสิ่งต่างๆเช่นfoo(bar <- 1:10)งาน (และbarถูกสร้างขึ้น) แต่foo(bar = 1:10)อาจล้มเหลวเนื่องจากbarไม่ใช่ข้อโต้แย้งfooและจะไม่สร้างbarขึ้นด้วย
Gavin Simpson

2
ทำไมค่าสัมประสิทธิ์ของx3 NA?
ziyuang

6

ส่วนขยายของวิธีการของ juba คือการใช้reformulateฟังก์ชันที่ได้รับการออกแบบมาอย่างชัดเจนสำหรับงานดังกล่าว

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

สำหรับตัวอย่างใน OP วิธีแก้ปัญหาที่ง่ายที่สุดคือ

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

หรือ

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

หมายเหตุว่าการเพิ่มตัวแปรที่จะ data.frame ในd <- cbind(y, d)เป็นที่ต้องการไม่เพียงเพราะจะช่วยให้การใช้งานของreformulateแต่ยังเพราะมันช่วยให้การใช้งานในอนาคตของวัตถุในการทำงานเช่นlmpredict


2

ฉันสร้างโซลูชันreformulateนี้ไม่สนใจว่าชื่อตัวแปรมีช่องว่างสีขาวหรือไม่

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

คุณสามารถตรวจสอบแพ็กเกจleapsและโดยเฉพาะฟังก์ชันregsubsets() ฟังก์ชันสำหรับการเลือกรุ่น ตามที่ระบุไว้ในเอกสาร:

การเลือกโมเดลโดยการค้นหาแบบละเอียดเดินหน้าหรือถอยหลังตามลำดับหรือการแทนที่ตามลำดับ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.