ดึงค่า p และ r-squared จากการถดถอยเชิงเส้น


179

คุณดึงค่า p ออกมาได้อย่างไร (สำหรับความสำคัญของสัมประสิทธิ์ของตัวแปรอธิบายเดียวที่ไม่เป็นศูนย์) และค่า R-squared จากตัวแบบการถดถอยเชิงเส้นอย่างง่าย? ตัวอย่างเช่น...

x = cumsum(c(0, runif(100, -1, +1)))
y = cumsum(c(0, runif(100, -1, +1)))
fit = lm(y ~ x)
summary(fit)

ฉันรู้ว่าsummary(fit) จะแสดงค่า p และค่า R-squared แต่ฉันต้องการที่จะสามารถติดเหล่านี้เป็นตัวแปรอื่น ๆ


มันจะแสดงเฉพาะค่าถ้าคุณไม่ได้กำหนดเอาท์พุทให้กับวัตถุ (เช่นr <- summary(lm(rnorm(10)~runif(10)))ไม่แสดงอะไร)
Joshua Ulrich

คำตอบ:


157

R-squared : คุณสามารถคืนค่า R-Squared summary(fit)$r.squaredโดยตรงจากวัตถุสรุป ดูnames(summary(fit))รายการทั้งหมดที่คุณสามารถแยกได้โดยตรง

Model p-value:หากคุณต้องการได้รับ p-value ของโมเดลการถดถอยโดยรวม บล็อกนี้โพสต์จะสรุปฟังก์ชันเพื่อส่งคืนค่า p:

lmp <- function (modelobject) {
    if (class(modelobject) != "lm") stop("Not an object of class 'lm' ")
    f <- summary(modelobject)$fstatistic
    p <- pf(f[1],f[2],f[3],lower.tail=F)
    attributes(p) <- NULL
    return(p)
}

> lmp(fit)
[1] 1.622665e-05

ในกรณีของการถดถอยอย่างง่าย ๆ ด้วยตัวทำนายค่าหนึ่งค่า p-value ของโมเดลและค่า p สำหรับสัมประสิทธิ์จะเท่ากัน

ค่าสัมประสิทธิ์ p:หากคุณมีตัวทำนายมากกว่าหนึ่งตัวค่าข้างต้นจะคืนค่า p-value ของแบบจำลองและค่า p สำหรับค่าสัมประสิทธิ์สามารถดึงออกมาได้โดยใช้:

summary(fit)$coefficients[,4]  

อีกวิธีหนึ่งคุณสามารถคว้าค่า p-value ของค่าสัมประสิทธิ์จากanova(fit)วัตถุในลักษณะที่คล้ายกับวัตถุสรุปข้างต้น


13
เป็นบิตดีกว่าการใช้inheritsมากกว่าclassโดยตรง และบางทีคุณอาจต้องการunname(pf(f[1],f[2],f[3],lower.tail=F))?
hadley

150

ขอให้สังเกตว่าsummary(fit)สร้างวัตถุที่มีข้อมูลทั้งหมดที่คุณต้องการ เวกเตอร์เบต้า, se, t และ p ถูกเก็บไว้ในนั้น รับค่า p โดยเลือกคอลัมน์ที่ 4 ของเมทริกซ์สัมประสิทธิ์ (เก็บไว้ในวัตถุสรุป):

summary(fit)$coefficients[,4] 
summary(fit)$r.squared

ลอง str(summary(fit))ดูข้อมูลทั้งหมดที่วัตถุนี้มี

แก้ไข: ฉันได้อ่านคำตอบของ Chase ที่ผิดซึ่งโดยทั่วไปจะบอกคุณถึงวิธีการได้รับสิ่งที่ฉันให้ที่นี่


11
หมายเหตุ: นี่เป็นวิธีการเดียวที่ให้คุณเข้าถึงค่า p ของการสกัดกั้นได้ง่ายเช่นเดียวกับตัวทำนายอื่น ๆ เท่าที่ผ่านมาดีที่สุด
Daniel Egan

2
นี่คือคำตอบที่ถูก คำตอบที่ติดอันดับไม่ทำงานสำหรับฉัน
คริส

8
หากคุณต้องการเข้าถึง P-VALUE ได้ง่ายให้ใช้คำตอบนี้ ทำไมคุณถึงต้องเขียนฟังก์ชั่นหลายบรรทัดหรือสร้างวัตถุใหม่ (เช่นเอาท์พุท anova) เมื่อคุณต้องดูยากขึ้นเล็กน้อยเพื่อหาค่า p ในเอาต์พุตสรุปเอง ในการแยกค่า p แต่ละค่าด้วยตนเองคุณต้องเพิ่มหมายเลขแถวในคำตอบของ Vincent: ตัวอย่างเช่นsummary(fit)$coefficients[1,4] สำหรับ ntercept
theforestecologist

2
หมายเหตุ: วิธีนี้ใช้ได้กับรุ่นที่สร้างขึ้นโดยใช้lm()แต่ใช้ไม่ได้กับgls()รุ่น
วิทยาศาสตร์ด้านป่าไม้

3
คำตอบของ Chase ส่งคืนค่า p ของโมเดลคำตอบนี้ส่งคืนค่า p ของสัมประสิทธิ์ ในกรณีของการถดถอยอย่างง่ายพวกมันเหมือนกัน แต่ในกรณีของแบบจำลองที่มีตัวทำนายหลายตัวพวกมันจะไม่เหมือนกัน ดังนั้นคำตอบทั้งสองนั้นมีประโยชน์ขึ้นอยู่กับสิ่งที่คุณต้องการแยก
Jeromy Anglim

44

คุณสามารถมองเห็นโครงสร้างของวัตถุที่ส่งกลับโดยโดยการเรียกsummary() แต่ละชิ้นสามารถเข้าถึงได้โดยใช้str(summary(fit)) $P-ค่าสำหรับสถิติ F anovaจะมีได้ง่ายขึ้นจากวัตถุที่ส่งกลับโดย

โดยสรุปคุณสามารถทำสิ่งนี้:

rSquared <- summary(fit)$r.squared
pVal <- anova(fit)$'Pr(>F)'[1]

10
ใช้งานได้เฉพาะการถดถอยแบบไม่รวมค่าที่ p val ของการถดถอยนั้นเหมือนกันกับตัวทำนาย
Bakaburg

23

แม้ว่าคำตอบทั้งสองข้างต้นจะดี แต่ขั้นตอนการแยกส่วนของวัตถุนั้นกว้างกว่า

ในหลาย ๆ กรณีฟังก์ชันส่งคืนรายการและแต่ละคอมโพเนนต์สามารถเข้าถึงได้โดยใช้str()ซึ่งจะพิมพ์ส่วนประกอบพร้อมกับชื่อ จากนั้นคุณสามารถเข้าถึงได้โดยใช้ตัวดำเนินการ $myobject$componentnameคือ

ในกรณีของวัตถุ LM มีจำนวนของวิธีการที่กำหนดไว้ล่วงหน้าหนึ่งสามารถใช้เช่นcoef(), resid(), summary()ฯลฯ แต่คุณจะไม่เสมอโชคดีอย่างนั้น


23

ฉันเจอคำถามนี้ขณะสำรวจวิธีแก้ไขปัญหาที่แนะนำ ฉันคิดว่าสำหรับการอ้างอิงในอนาคตมันอาจจะคุ้มค่าที่จะปรับปรุงรายการคำตอบที่มีอยู่ด้วยโซลูชั่นที่ใช้broomแพคเกจ

โค้ดตัวอย่าง

x = cumsum(c(0, runif(100, -1, +1)))
y = cumsum(c(0, runif(100, -1, +1)))
fit = lm(y ~ x)
require(broom)
glance(fit)

ผล

>> glance(fit)
  r.squared adj.r.squared    sigma statistic    p.value df    logLik      AIC      BIC deviance df.residual
1 0.5442762     0.5396729 1.502943  118.2368 1.3719e-18  2 -183.4527 372.9055 380.7508 223.6251          99

หมายเหตุด้านข้าง

ฉันคิดว่าglanceฟังก์ชั่นนี้มีประโยชน์เพราะมันสรุปค่าคีย์อย่างเป็นระเบียบ ผลลัพธ์จะถูกจัดเก็บในรูปแบบdata.frameที่ง่ายต่อการจัดการ:

>> class(glance(fit))
[1] "data.frame"

นี่เป็นคำตอบที่ยอดเยี่ยม!
Andrew Brēza

9

การขยายคำตอบของ @Vincent :

สำหรับlm()รุ่นที่สร้างขึ้น:

summary(fit)$coefficients[,4]   ##P-values 
summary(fit)$r.squared          ##R squared values

สำหรับgls()รุ่นที่สร้างขึ้น:

summary(fit)$tTable[,4]         ##P-values
##R-squared values are not generated b/c gls uses max-likelihood not Sums of Squares

หากต้องการแยกค่า p แต่ละค่าด้วยตนเองคุณต้องเพิ่มหมายเลขแถวลงในรหัส:

ตัวอย่างเช่นในการเข้าถึงค่า p ของการสกัดกั้นในสรุปแบบจำลองทั้งสอง:

summary(fit)$coefficients[1,4]
summary(fit)$tTable[1,4]  
  • หมายเหตุคุณสามารถแทนที่หมายเลขคอลัมน์ด้วยชื่อคอลัมน์ในแต่ละอินสแตนซ์ด้านบน:

    summary(fit)$coefficients[1,"Pr(>|t|)"]  ##lm 
    summary(fit)$tTable[1,"p-value"]         ##gls 

หากคุณยังไม่แน่ใจว่าจะเข้าถึงรูปแบบค่าได้อย่างไรตารางสรุปใช้str()เพื่อกำหนดโครงสร้างของตารางสรุป:

str(summary(fit))

7

นี่เป็นวิธีที่ง่ายที่สุดในการดึงค่า p:

coef(summary(modelname))[, "Pr(>|t|)"]

1
ฉันลองใช้วิธีนี้ แต่มันจะล้มเหลวถ้าตัวแบบเชิงเส้นมีคำศัพท์ NA ใด ๆ
j_v_wow_d

5

ฉันใช้ฟังก์ชัน lmp นี้หลายครั้ง

และเมื่อถึงจุดหนึ่งฉันตัดสินใจที่จะเพิ่มคุณสมบัติใหม่เพื่อปรับปรุงการวิเคราะห์ข้อมูล ฉันไม่เชี่ยวชาญใน R หรือสถิติ แต่คนมักจะดูข้อมูลต่าง ๆ ของการถดถอยเชิงเส้น:

  • p-value
  • a และ b
  • r²อะเรย์
  • และแน่นอนว่าลักษณะของการแจกแจงพอยต์

ลองมาตัวอย่างกัน คุณมีที่นี่

นี่คือตัวอย่างที่ทำซ้ำได้ด้วยตัวแปรที่แตกต่างกัน:

Ex<-structure(list(X1 = c(-36.8598, -37.1726, -36.4343, -36.8644, 
-37.0599, -34.8818, -31.9907, -37.8304, -34.3367, -31.2984, -33.5731
), X2 = c(64.26, 63.085, 66.36, 61.08, 61.57, 65.04, 72.69, 63.83, 
67.555, 76.06, 68.61), Y1 = c(493.81544, 493.81544, 494.54173, 
494.61364, 494.61381, 494.38717, 494.64122, 493.73265, 494.04246, 
494.92989, 494.98384), Y2 = c(489.704166, 489.704166, 490.710962, 
490.653212, 490.710612, 489.822928, 488.160904, 489.747776, 490.600579, 
488.946738, 490.398958), Y3 = c(-19L, -19L, -19L, -23L, -30L, 
-43L, -43L, -2L, -58L, -47L, -61L)), .Names = c("X1", "X2", "Y1", 
"Y2", "Y3"), row.names = c(NA, 11L), class = "data.frame")


library(reshape2)
library(ggplot2)
Ex2<-melt(Ex,id=c("X1","X2"))
colnames(Ex2)[3:4]<-c("Y","Yvalue")
Ex3<-melt(Ex2,id=c("Y","Yvalue"))
colnames(Ex3)[3:4]<-c("X","Xvalue")

ggplot(Ex3,aes(Xvalue,Yvalue))+
          geom_smooth(method="lm",alpha=0.2,size=1,color="grey")+
          geom_point(size=2)+
          facet_grid(Y~X,scales='free')


#Use the lmp function

lmp <- function (modelobject) {
  if (class(modelobject) != "lm") stop("Not an object of class 'lm' ")
  f <- summary(modelobject)$fstatistic
    p <- pf(f[1],f[2],f[3],lower.tail=F)
    attributes(p) <- NULL
    return(p)
    }

# create function to extract different informations from lm

lmtable<-function (var1,var2,data,signi=NULL){
  #var1= y data : colnames of data as.character, so "Y1" or c("Y1","Y2") for example
  #var2= x data : colnames of data as.character, so "X1" or c("X1","X2") for example
  #data= data in dataframe, variables in columns
  # if signi TRUE, round p-value with 2 digits and add *** if <0.001, ** if < 0.01, * if < 0.05.

  if (class(data) != "data.frame") stop("Not an object of class 'data.frame' ")
  Tabtemp<-data.frame(matrix(NA,ncol=6,nrow=length(var1)*length(var2)))
  for (i in 1:length(var2))
       {
  Tabtemp[((length(var1)*i)-(length(var1)-1)):(length(var1)*i),1]<-var1
  Tabtemp[((length(var1)*i)-(length(var1)-1)):(length(var1)*i),2]<-var2[i]
  colnames(Tabtemp)<-c("Var.y","Var.x","p-value","a","b","r^2")

  for (n in 1:length(var1))
  {
  Tabtemp[(((length(var1)*i)-(length(var1)-1))+n-1),3]<-lmp(lm(data[,var1[n]]~data[,var2[i]],data))

  Tabtemp[(((length(var1)*i)-(length(var1)-1))+n-1),4]<-coef(lm(data[,var1[n]]~data[,var2[i]],data))[1]

  Tabtemp[(((length(var1)*i)-(length(var1)-1))+n-1),5]<-coef(lm(data[,var1[n]]~data[,var2[i]],data))[2]

  Tabtemp[(((length(var1)*i)-(length(var1)-1))+n-1),6]<-summary(lm(data[,var1[n]]~data[,var2[i]],data))$r.squared
  }
  }

  signi2<-data.frame(matrix(NA,ncol=3,nrow=nrow(Tabtemp)))
  signi2[,1]<-ifelse(Tabtemp[,3]<0.001,paste0("***"),ifelse(Tabtemp[,3]<0.01,paste0("**"),ifelse(Tabtemp[,3]<0.05,paste0("*"),paste0(""))))
  signi2[,2]<-round(Tabtemp[,3],2)
  signi2[,3]<-paste0(format(signi2[,2],digits=2),signi2[,1])

  for (l in 1:nrow(Tabtemp))
    {
  Tabtemp$"p-value"[l]<-ifelse(is.null(signi),
         Tabtemp$"p-value"[l],
         ifelse(isTRUE(signi),
                paste0(signi2[,3][l]),
                Tabtemp$"p-value"[l]))
  }

   Tabtemp
}

# ------- EXAMPLES ------

lmtable("Y1","X1",Ex)
lmtable(c("Y1","Y2","Y3"),c("X1","X2"),Ex)
lmtable(c("Y1","Y2","Y3"),c("X1","X2"),Ex,signi=TRUE)

แน่นอนว่ามีวิธีแก้ปัญหาที่เร็วกว่าฟังก์ชั่นนี้ แต่ใช้งานได้


2

สำหรับค่า p สุดท้ายที่แสดงในตอนท้ายsummary()ฟังก์ชันใช้pf()ในการคำนวณจากsummary(fit)$fstatisticค่า

fstat <- summary(fit)$fstatistic
pf(fstat[1], fstat[2], fstat[3], lower.tail=FALSE)

แหล่งที่มา: [1] , [2]


1
x = cumsum(c(0, runif(100, -1, +1)))
y = cumsum(c(0, runif(100, -1, +1)))
fit = lm(y ~ x)
> names(summary(fit))
[1] "call"          "terms"        
 [3] "residuals"     "coefficients" 
 [5] "aliased"       "sigma"        
 [7] "df"            "r.squared"    
 [9] "adj.r.squared" "fstatistic"   
[11] "cov.unscaled" 
    summary(fit)$r.squared

1
สนใจที่จะให้คำอธิบายแม้ว่าสั้น ๆ ว่าทำไมรหัสนี้ทำงานอย่างไร
aribeiro

วิธีนี้จะปรับปรุงคำตอบที่มีอยู่ (และโดยเฉพาะคำตอบที่ยอมรับได้)
Ben Bolker

0

อีกทางเลือกหนึ่งคือการใช้ฟังก์ชั่น cor.test แทน lm:

> x <- c(44.4, 45.9, 41.9, 53.3, 44.7, 44.1, 50.7, 45.2, 60.1)
> y <- c( 2.6,  3.1,  2.5,  5.0,  3.6,  4.0,  5.2,  2.8,  3.8)

> mycor = cor.test(x,y)
> mylm = lm(x~y)

# r and rsquared:
> cor.test(x,y)$estimate ** 2
      cor 
0.3262484 
> summary(lm(x~y))$r.squared
[1] 0.3262484

# P.value 

> lmp(lm(x~y))  # Using the lmp function defined in Chase's answer
[1] 0.1081731
> cor.test(x,y)$p.value
[1] 0.1081731

0

ใช้:

(summary(fit))$coefficients[***num***,4]

โดยที่numเป็นตัวเลขซึ่งหมายถึงแถวของเมทริกซ์สัมประสิทธิ์ มันจะขึ้นอยู่กับจำนวนฟีเจอร์ที่คุณมีในโมเดลของคุณและฟีเจอร์ที่คุณต้องการดึงค่า p ออกมา ตัวอย่างเช่นหากคุณมีตัวแปรเพียงตัวเดียวจะมีค่า p หนึ่งค่าสำหรับการสกัดกั้นซึ่งจะเป็น [1,4] และอีกตัวแปรหนึ่งสำหรับตัวแปรจริงของคุณซึ่งจะเป็น [2,4] ดังนั้นคุณnumจะเป็น 2

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