Dodanie linii regresji do ggplot

120

Bardzo się staram dodać linię regresji na wykresie ggplot. Najpierw próbowałem z abline, ale nie udało mi się to zrobić. Potem spróbowałem tego ...

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)

Ale to też nie działa.

Remi.b
źródło

Odpowiedzi:

170

Generalnie, aby zapewnić swoją własną formułę należy użyć argumentów xi yże będzie odpowiadać wartości podanej na ggplot()- w tym przypadku xbędzie interpretowany jako x.ploti yjak y.plot. Więcej informacji o metodach wygładzania i formule można znaleźć na stronie pomocy funkcji, stat_smooth()ponieważ jest to domyślna statystyka używana przez geom_smooth().

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

Jeśli używasz tych samych wartości xiy, które podałeś w ggplot()wywołaniu i potrzebujesz wykreślić linię regresji liniowej, nie musisz używać formuły w środku geom_smooth(), po prostu podaj method="lm".

ggplot(data,aes(x.plot, y.plot)) +
  stat_summary(fun.data= mean_cl_normal) + 
  geom_smooth(method='lm')
Didzis Elferts
źródło
46

Jak właśnie się domyśliłem, jeśli masz model dopasowany do wielokrotnej regresji liniowej , powyższe rozwiązanie nie zadziała.

Musisz ręcznie utworzyć linię jako ramkę danych, która zawiera przewidywane wartości dla oryginalnej ramki danych (w twoim przypadku data).

Wyglądałoby to tak:

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

Wiele LR

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

Pojedynczy LR

StefanK
źródło
1
Jedną rzeczą, na którą należy zwrócić uwagę, jest konwencja lm (y ~ x). Trochę się odwróciłem do drugiego czytania, ponieważ zmienna, którą „przewidujesz”, znajduje się na osi X. Świetna odpowiedź.
colorlace
14

Oczywiste rozwiązanie wykorzystujące geom_abline:

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

Gdzie data.lmjest lmobiekt i data.lm$coefficientswygląda mniej więcej tak:

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

Identyczne w praktyce jest użycie stat_functiondo wykreślenia linii regresji w funkcji x, wykorzystując predict:

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

Jest to trochę mniej wydajne, ponieważ domyślnie n=101obliczane są punkty, ale znacznie bardziej elastyczne, ponieważ wykreśla krzywą predykcji dla dowolnego modelu, który obsługuje predict, na przykład nieliniowy npregz pakietu np.

Uwaga: Jeśli użyjesz scale_x_continuouslub scale_y_continuousniektóre wartości mogą zostać obcięte, a tym samym geom_smoothmogą nie działać poprawnie. Zamiast tego użyj, coord_cartesianaby powiększyć .

qwr
źródło
2
Dzięki temu nigdy nie martwisz się o kolejność formuł lub po prostu dodawanie +0, możesz użyć nazw. data.lm$coefficients[['(Intercept)']]i data.lm$coefficients[['DepDelay']].
Ufos
(Prawie) zawsze (Intercept)będzie wymienione jako pierwsze. Nazwy sprawiają, że kod jest wyraźniejszy.
qwr
Myślę, że to najlepsza odpowiedź - jest najbardziej wszechstronna.
Arranjdavis
4

Znalazłem tę funkcję na blogu

 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)))
    }`

po załadowaniu funkcji możesz po prostu

ggplotRegression(fit)

możesz też iść ggplotregression( y ~ x + z + Q, data)

Mam nadzieję że to pomoże.

YellowEagle
źródło
2

Jeśli chcesz dopasować inne typy modeli, takie jak krzywa dawka-odpowiedź przy użyciu modeli logistycznych, musisz również utworzyć więcej punktów danych za pomocą funkcji przewidywania, jeśli chcesz uzyskać gładszą linię regresji:

dopasowanie: dopasowanie krzywej regresji logistycznej

#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)))
user3436882
źródło