extraer valores de p y r al cuadrado de una regresión lineal

179

¿Cómo extrae el valor p (para la importancia del coeficiente de la variable explicativa única que no es cero) y el valor R cuadrado de un modelo de regresión lineal simple? Por ejemplo...

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

Sé que summary(fit) muestra el valor p y el valor R cuadrado, pero quiero poder pegarlos en otras variables.

grautur
fuente
Solo muestra los valores si no asigna la salida a un objeto (por ejemplo r <- summary(lm(rnorm(10)~runif(10))), no muestra nada).
Joshua Ulrich

Respuestas:

157

r-cuadrado : puede devolver el valor de r cuadrado directamente desde el objeto de resumen summary(fit)$r.squared. Consulte names(summary(fit))para obtener una lista de todos los elementos que puede extraer directamente.

Valor p del modelo: si desea obtener el valor p del modelo de regresión general, esta publicación de blog describe una función para devolver el valor 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

En el caso de una regresión simple con un predictor, el valor p del modelo y el valor p para el coeficiente serán los mismos.

Valores p de coeficiente: si tiene más de un predictor, lo anterior devolverá el valor p del modelo, y el valor p para los coeficientes se puede extraer usando:

summary(fit)$coefficients[,4]  

Alternativamente, puede tomar el valor p de los coeficientes del anova(fit)objeto de manera similar al objeto de resumen anterior.

Persecución
fuente
13
Es un poco mejor usarlo inheritsque classdirectamente. Y tal vez quieres unname(pf(f[1],f[2],f[3],lower.tail=F))?
hadley
150

Observe que summary(fit)genera un objeto con toda la información que necesita. Los vectores beta, se, typ se almacenan en él. Obtenga los valores p seleccionando la cuarta columna de la matriz de coeficientes (almacenada en el objeto de resumen):

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

Intenta str(summary(fit))ver toda la información que contiene este objeto.

Editar: había leído mal la respuesta de Chase, que básicamente te dice cómo llegar a lo que doy aquí.

Vincent
fuente
11
Nota: este es el único método que le brinda acceso fácil al valor p de la intercepción, así como a los otros predictores. De lejos, lo mejor de lo anterior.
Daniel Egan
2
Esta es la respuesta correcta. La respuesta mejor calificada NO funcionó para mí.
Chris
8
SI DESEA FÁCIL ACCESO AL VALOR P, USE ESTA RESPUESTA. ¿Por qué pasaría por escribir funciones de varias líneas o crear nuevos objetos (es decir, salidas anova), cuando solo tiene que buscar un poco más para encontrar el valor p en la salida de resumen en sí. Para aislar un valor p individual en sí mismo, agregaría un número de fila a la respuesta de Vincent: por ejemplo, summary(fit)$coefficients[1,4] para la interpretación
theforestecologist
2
Nota: este método funciona para modelos creados usando lm()pero no funciona para gls()modelos.
theforestecologist
3
La respuesta de Chase devuelve el valor p del modelo, esta respuesta devuelve el valor p de los coeficientes. En el caso de una regresión simple, son iguales, pero en el caso de un modelo con múltiples predictores, no son lo mismo. Por lo tanto, ambas respuestas son útiles dependiendo de lo que quieras extraer.
Jeromy Anglim
44

Puede ver la estructura del objeto devuelto summary()llamando str(summary(fit)). Se puede acceder a cada pieza usando $. El valor p para la estadística F se obtiene más fácilmente del objeto devuelto por anova.

De manera concisa, puedes hacer esto:

rSquared <- summary(fit)$r.squared
pVal <- anova(fit)$'Pr(>F)'[1]
jberg
fuente
10
esto funciona solo para regresiones univariadas donde el valor de la regresión es el mismo del predictor
Bakaburg
23

Si bien las dos respuestas anteriores son buenas, el procedimiento para extraer partes de objetos es más general.

En muchos casos, las funciones devuelven listas y se puede acceder a los componentes individuales mediante el str()cual imprimirá los componentes junto con sus nombres. Luego puede acceder a ellos utilizando el operador $, es decir myobject$componentname.

En el caso de objetos LM, hay una serie de métodos predefinidos se pueden usar como coef(), resid(), summary()etc, pero no siempre será tan afortunado.

richiemorrisroe
fuente
23

Encontré esta pregunta mientras exploraba soluciones sugeridas para un problema similar; Supongo que para futuras referencias puede valer la pena actualizar la lista de respuestas disponible con una solución que utilicebroom paquete.

Código de muestra

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

Resultados

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

Notas al margen

Creo que la glancefunción es útil ya que resume claramente los valores clave. Los resultados se almacenan como lo data.frameque facilita la manipulación adicional:

>> class(glance(fit))
[1] "data.frame"
Konrad
fuente
¡Esta es una respuesta genial!
Andrew Brēza
9

Extensión de @Vincent 's respuesta :

Para lm()modelos generados:

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

Para gls()modelos generados:

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

Para aislar un valor p individual en sí mismo, debe agregar un número de fila al código:

Por ejemplo, para acceder al valor p de la intersección en ambos resúmenes del modelo:

summary(fit)$coefficients[1,4]
summary(fit)$tTable[1,4]  
  • Tenga en cuenta que puede reemplazar el número de columna con el nombre de la columna en cada una de las instancias anteriores:

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

Si aún no está seguro de cómo acceder a un formulario de valores, use la tabla de resumen str()para descubrir la estructura de la tabla de resumen:

str(summary(fit))
el forestalteólogo
fuente
7

Esta es la forma más fácil de extraer los valores p:

coef(summary(modelname))[, "Pr(>|t|)"]
RTrain3k
fuente
1
Intenté este método, pero fallará si el modelo lineal contiene algún término de NA
j_v_wow_d
5

Usé esta función lmp muchas veces.

Y en un momento decidí agregar nuevas características para mejorar el análisis de datos. No soy experto en R ni en estadísticas, pero la gente suele buscar información diferente de una regresión lineal:

  • valor p
  • a y B
  • y, por supuesto, el aspecto de la distribución de puntos

Tengamos un ejemplo. Tienes aqui

Aquí un ejemplo reproducible con diferentes variables:

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)

Ciertamente hay una solución más rápida que esta función, pero funciona.

Dorian Grv
fuente
2

Para el valor p final que se muestra al final de summary(), la función se utiliza pf()para calcular a partir de los summary(fit)$fstatisticvalores.

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

Fuente: [1] , [2]

Saftever
fuente
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
Jojo
fuente
1
¿Le gustaría dar una explicación, aunque sea brevemente, sobre por qué funciona este código?
aribeiro
¿Cómo mejora esto en las respuestas existentes (y en particular la respuesta aceptada)?
Ben Bolker
0

Otra opción es usar la función cor.test, en lugar de 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
dalloliogm
fuente
0

Utilizar:

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

donde numes un número que denota la fila de la matriz de coeficientes. Dependerá de la cantidad de características que tenga en su modelo y para cuál desea extraer el valor p. Por ejemplo, si solo tiene una variable, habrá un valor p para la intersección que será [1,4] y el siguiente para su variable real que será [2,4]. Entonces tu numserá 2.

Tirtha
fuente