витягнути р-значення та r-квадрат з лінійної регресії


179

Як ви виводите значення р (якщо значення коефіцієнта єдиної пояснювальної змінної є ненульовим) та значення R-квадрата з простої лінійної регресійної моделі? Наприклад...

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-квадрата, але я хочу мати змогу вставити їх в інші змінні.


Він відображає значення лише у тому випадку, якщо ви не призначите вихід об'єкту (наприклад, r <- summary(lm(rnorm(10)~runif(10)))нічого не відображає).
Джошуа Ульріх

Відповіді:


157

r-квадрат : Ви можете повернути значення r-квадрата безпосередньо з об'єкта зведення summary(fit)$r.squared. Перегляньте names(summary(fit))список усіх предметів, які можна витягти безпосередньо.

Модель p-значення: Якщо ви хочете отримати p-значення загальної регресійної моделі, цей пост у блозі окреслює функцію повернення 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-значення та p-значення для коефіцієнта будуть однаковими.

Коефіцієнт p-значення: Якщо у вас є більше одного прогноктора, то вищезгадане поверне модельне p-значення, а p-значення для коефіцієнтів можна отримати, використовуючи:

summary(fit)$coefficients[,4]  

Крім того, ви можете схопити p-значення коефіцієнтів від anova(fit)об'єкта аналогічно вищезведеному об'єкту.


13
Це трохи краще використовувати, inheritsа не classбезпосередньо. А може, ти хочеш unname(pf(f[1],f[2],f[3],lower.tail=F))?
Хадлі

150

Зауважте, що summary(fit)генерується об’єкт з усією необхідною інформацією. Вектори бета, se, t і p зберігаються в ньому. Отримайте значення p, вибравши 4-й стовпчик матриці коефіцієнтів (зберігається в об'єкті підсумків):

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

Спробуйте str(summary(fit))переглянути всю інформацію, яку містить цей об’єкт.

Редагувати: Я неправильно прочитав відповідь Чейза, яка в основному говорить вам, як дістатися до того, що я даю тут.


11
Примітка: це єдиний метод, який дає вам легкий доступ до p-значення перехоплення, а також до інших прогнозів. На сьогоднішній день найкраще.
Даніель Еган

2
Це ПРАВА відповідь. Відповідь з найвищим рейтингом НЕ працював для мене.
Кріс,

8
ЯКЩО Ви хочете ЛЕГИЙ ДОСТУП ДО П-ЦІННОСТІ, ВИКОРИСТУЙТЕ ЦІЙ ВІДПОВІДЬ. Чому ви переходите до написання багаторядкових функцій або створення нових об'єктів (тобто, anova output), коли вам потрібно буде трохи важче подивитися на значення p у самому підсумковому висновку. Для виділення окремого сам р-значення, потрібно додати номер рядка у відповідь Вінсент: наприклад, summary(fit)$coefficients[1,4] для thei ntercept
theforestecologist

2
Примітка. Цей метод працює для моделей, створених за допомогою, lm()але не працює для gls()моделей.
theforestecologist

3
Відповідь Чейза повертає p-значення моделі, ця відповідь повертає p-значення коефіцієнтів. У випадку простої регресії вони однакові, але у випадку з моделлю з декількома предикторами вони не однакові. Таким чином, обидві відповіді корисні залежно від того, що ви хочете витягти.
Джеромі Англім

44

Ви можете бачити структуру об'єкта, що повертається summary(), зателефонувавши str(summary(fit)). Кожен фрагмент можна отримати за допомогою $. Значення p для статистики F легше було від об'єкта, повернутого anova.

Точно, ви можете це зробити:

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

10
це працює лише для одноманітних регресій, де р вал регресії той самий, що й
прогноктор

23

Хоча обидві відповіді вище хороші, процедура вилучення частин предметів є більш загальною.

У багатьох випадках до функцій повертаються списки, а до окремих компонентів можна отримати доступ, використовуючи для str()цього друк компонентів разом з їх назвами. Потім ви можете отримати доступ до них за допомогою оператора $, тобто myobject$componentname.

У разі об'єктів лм, існує цілий ряд зумовлених методів можна використовувати , наприклад , як 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"

Це чудова відповідь!
Андрій Бреза

9

Розширення @Vincent «s відповідь :

Для 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 або статистики, але люди зазвичай дивляться на різну інформацію лінійної регресії:

  • р-значення
  • а і б
  • і, звичайно, аспект розподілу точок

Будемо мати приклад. Ви тут

Ось відтворюваний приклад з різними змінними:

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
Потрібно дати пояснення, навіть якщо коротко, чому цей код працює?
арібейро

як це покращується на існуючих відповідях (і зокрема на прийнятій відповіді)?
Бен Болкер

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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.