Agregar una línea de regresión en un ggplot

120

Estoy tratando de agregar una línea de regresión en un ggplot. Primero probé con abline pero no logré que funcionara. Entonces probé esto ...

data = data.frame(x.plot=rep(seq(1,5),10),y.plot=rnorm(50))
ggplot(data,aes(x.plot,y.plot))+stat_summary(fun.data=mean_cl_normal) +
   geom_smooth(method='lm',formula=data$y.plot~data$x.plot)

Pero tampoco está funcionando.

Remi.b
fuente

Respuestas:

170

En general, para proporcionar su propia fórmula se debe utilizar argumentos xy yque corresponderá a los valores que proporcione en ggplot()- en este caso, xserá interpretado como x.ploty ycomo y.plot. Puede encontrar más información sobre los métodos de suavizado y la fórmula en la página de ayuda de la función, stat_smooth()ya que es la estadística predeterminada utilizada por geom_smooth().

ggplot(data,aes(x.plot, y.plot)) +
  stat_summary(fun.data=mean_cl_normal) + 
  geom_smooth(method='lm', formula= y~x)

Si está utilizando los mismos valores xey que proporcionó en la ggplot()llamada y necesita trazar la línea de regresión lineal, entonces no necesita usar la fórmula en el interior geom_smooth(), solo proporcione el method="lm".

ggplot(data,aes(x.plot, y.plot)) +
  stat_summary(fun.data= mean_cl_normal) + 
  geom_smooth(method='lm')
Didzis Elferts
fuente
46

Como acabo de imaginar, en caso de que tenga un modelo ajustado en regresión lineal múltiple , la solución mencionada anteriormente no funcionará.

Debe crear su línea manualmente como un marco de datos que contiene valores predichos para su marco de datos original (en su caso data).

Se vería así:

# read dataset
df = mtcars

# create multiple linear model
lm_fit <- lm(mpg ~ cyl + hp, data=df)
summary(lm_fit)

# save predictions of the model in the new data frame 
# together with variable you want to plot against
predicted_df <- data.frame(mpg_pred = predict(lm_fit, df), hp=df$hp)

# this is the predicted line of multiple linear regression
ggplot(data = df, aes(x = mpg, y = hp)) + 
  geom_point(color='blue') +
  geom_line(color='red',data = predicted_df, aes(x=mpg_pred, y=hp))

LR múltiple

# this is predicted line comparing only chosen variables
ggplot(data = df, aes(x = mpg, y = hp)) + 
  geom_point(color='blue') +
  geom_smooth(method = "lm", se = FALSE)

LR único

StefanK
fuente
1
Una cosa a tener en cuenta es que la convención es lm (y ~ x). Me di la vuelta un poco para una segunda lectura de esto, ya que la variable que está 'prediciendo' está en el eje x. Sin embargo, gran respuesta.
colorlace
14

La solución obvia usando geom_abline:

geom_abline(slope = data.lm$coefficients[2], intercept = data.lm$coefficients[1])

¿Dónde data.lmhay un lmobjeto y se data.lm$coefficientsparece a esto?

data.lm$coefficients
(Intercept)    DepDelay 
  -2.006045    1.025109 

En la práctica, es idéntico usar stat_functionpara trazar la línea de regresión como una función de x, haciendo uso de predict:

stat_function(fun = function(x) predict(data.lm, newdata = data.frame(DepDelay=x)))

Esto es un poco menos eficiente ya que por defecto n=101se calculan los puntos, pero mucho más flexible ya que trazará una curva de predicción para cualquier modelo que admita predict, como no lineal npregdel paquete np.

Nota: Si utiliza scale_x_continuouso, scale_y_continuousalgunos valores pueden cortarse y, por lo tanto, es geom_smoothposible que no funcionen correctamente. Use coord_cartesianpara hacer zoom en su lugar .

qwr
fuente
2
Y por lo tanto, nunca se preocupa por ordenar sus fórmulas o simplemente agregar un nombre +0que puede usar. data.lm$coefficients[['(Intercept)']]y data.lm$coefficients[['DepDelay']].
Ovnis
(Casi) siempre (Intercept)aparecerá en primer lugar. Los nombres hacen que el código sea más claro.
qwr
Creo que esta es la mejor respuesta, es la más versátil.
Arranjdavis
4

Encontré esta función en un blog.

 ggplotRegression <- function (fit) {

    `require(ggplot2)

    ggplot(fit$model, aes_string(x = names(fit$model)[2], y = names(fit$model)[1])) + 
      geom_point() +
      stat_smooth(method = "lm", col = "red") +
      labs(title = paste("Adj R2 = ",signif(summary(fit)$adj.r.squared, 5),
                         "Intercept =",signif(fit$coef[[1]],5 ),
                         " Slope =",signif(fit$coef[[2]], 5),
                         " P =",signif(summary(fit)$coef[2,4], 5)))
    }`

una vez que cargó la función, simplemente podría

ggplotRegression(fit)

también puedes ir por ggplotregression( y ~ x + z + Q, data)

Espero que esto ayude.

Águila Amarilla
fuente
2

Si desea ajustar otro tipo de modelos, como una curva de dosis-respuesta utilizando modelos logísticos, también necesitaría crear más puntos de datos con la función predecir si desea tener una línea de regresión más suave:

ajuste: su ajuste de una curva de regresión logística

#Create a range of doses:
mm <- data.frame(DOSE = seq(0, max(data$DOSE), length.out = 100))
#Create a new data frame for ggplot using predict and your range of new 
#doses:
fit.ggplot=data.frame(y=predict(fit, newdata=mm),x=mm$DOSE)

ggplot(data=data,aes(x=log10(DOSE),y=log(viability)))+geom_point()+
geom_line(data=fit.ggplot,aes(x=log10(x),y=log(y)))
usuario3436882
fuente