Functie om R2 (R-kwadraat) in R te berekenen

Ik heb een dataframe met geobserveerde en gemodelleerde data, en ik wil graag de R2-waarde berekenen. Ik had verwacht dat er een functie zou zijn die ik hiervoor zou kunnen aanroepen, maar kan er geen vinden. Ik weet dat ik mijn eigen kan schrijven en toepassen, maar mis ik iets voor de hand liggend? Ik wil zoiets als

obs <- 1:5
mod <- c(0.8,2.4,2,3,4.8)
df <- data.frame(obs, mod)
R2 <- rsq(df)
# 0.85

Antwoord 1, autoriteit 100%

Je hebt een beetje statistische kennis nodig om dit te zien. R-kwadraat tussen twee vectoren is gewoon het kwadraat van hun correlatie. U kunt uw functie dus definiëren als:

rsq <- function (x, y) cor(x, y) ^ 2

Sandipan’s antwoordlevert exact hetzelfde resultaat op (zie het volgende bewijs), maar zoals het er nu uitziet lijkt het meer leesbaar (vanwege de duidelijke $r.squared).


Laten we de statistieken doen

In principe passen we een lineaire regressie van yover xen berekenen we de verhouding van de regressiesom van kwadraten tot de totale kwadratensom.

lemma 1: een regressie y ~ xis gelijk aan y - mean(y) ~ x - mean(x)

lemma 2: bèta = cov(x, y) / var(x)

lemma 3: R.kwadraat = cor(x, y) ^ 2


Waarschuwing

R in het kwadraat tussen twee willekeurige vectoren xen y(van dezelfde lengte) is slechts een goede maatstaf voor hun lineaire relatie. Denk twee keer na!! R kwadraat tussen x + aen y + bzijn identiek voor elke constante shift aen b. Het is dus een zwakke of zelfs nutteloze maatstaf voor “goedheid van voorspelling”. Gebruik in plaats daarvan MSE of RMSE:

Ik ga akkoord met 42-‘s opmerking:

Het R-kwadraat wordt gerapporteerd door samenvattingsfuncties die zijn gekoppeld aan regressiefuncties. Maar alleen als een dergelijke schatting statistisch verantwoord is.

R-kwadraat kan een (maar niet de beste) maatstaf zijn voor ‘goodness of fit’. Maar er is geen rechtvaardiging dat het de goedheid van out-of-sample-voorspelling kan meten. Als u uw gegevens opsplitst in trainings- en testgedeelten en een regressiemodel op het trainingsgedeelte past, kunt u een geldige R-kwadraatwaarde krijgen voor het trainingsgedeelte, maar u kunt geen R-kwadraat op het testgedeelte berekenen. Sommige mensen hebben dit gedaan, maar ik ben het er niet mee eens.

Hier is een heel extreem voorbeeld:

preds <- 1:4/4
actual <- 1:4

De R-kwadraat tussen die twee vectoren is 1. Ja natuurlijk, één is gewoon een lineaire redding van de andere, zodat ze een perfecte lineaire relatie hebben. Maar denk je echt dat de predseen goede voorspelling is over actual??


In antwoord op woordenfordewise

Bedankt voor uw opmerkingen 1 , 2 en Ja Antwoord van details .

U hebt de procedure waarschijnlijk verkeerd begrepen. Gegeven twee vectoren xen y, passen we eerst een regressielijn y ~ xvervolgens berekenen regressiesom van vierkanten en totale som van vierkanten. Het lijkt erop dat je deze regressiestap overslaat en direct naar de som van vierkante berekening gaat. Dat is onjuist, sinds De partitie van de som van vierkanten houdt niet vast en je kunt r niet compueren ingezette op een consistente manier.

Zoals u hebt aangetoond, is dit slechts één manier om RQUARED RQUARED:

preds <- c(1, 2, 3)
actual <- c(2, 2, 4)
rss <- sum((preds - actual) ^ 2)  ## residual sum of squares
tss <- sum((actual - mean(actual)) ^ 2)  ## total sum of squares
rsq <- 1 - rss/tss
#[1] 0.25

Maar er is een andere:

regss <- sum((preds - mean(preds)) ^ 2) ## regression sum of squares
regss / tss
#[1] 0.75

Uw formule kan ook een negatieve waarde geven (de juiste waarde moet 1 zijn zoals hierboven vermeld in het gedeelte Waarschuwing).

preds <- 1:4 / 4
actual <- 1:4
rss <- sum((preds - actual) ^ 2)  ## residual sum of squares
tss <- sum((actual - mean(actual)) ^ 2)  ## total sum of squares
rsq <- 1 - rss/tss
#[1] -2.375

Laatste opmerking

Ik had nooit verwacht dat dit antwoord uiteindelijk zo lang zou kunnen duren toen ik mijn eerste antwoord 2 jaar geleden plaatste. Gezien de hoge meningen van deze thread, voel ik me echter verplicht om meer statistische details en discussies toe te voegen. Ik wil mensen niet misleiden dat ze, omdat ze zo gemakkelijk een R-kwadraat kunnen berekenen, overal R-kwadraat kunnen gebruiken.


Antwoord 2, autoriteit 27%

Waarom niet dit:

rsq <- function(x, y) summary(lm(y~x))$r.squared
rsq(obs, mod)
#[1] 0.8560185

Antwoord 3, autoriteit 18%

Je kunt de samenvatting ook gebruiken voor lineaire modellen:

summary(lm(obs ~ mod, data=df))$r.squared 

Antwoord 4, autoriteit 14%

Het is niet iets voor de hand liggend, maar het caret-pakket heeft een functie postResample()die “Een vector van prestatieschattingen” berekent volgens de documentatie. De “prestatieschattingen” zijn

  • RMSE
  • Rkwadraat
  • gemiddelde absolute fout (MAE)

en moeten op deze manier worden benaderd vanuit de vector

library(caret)
vect1 <- c(1, 2, 3)
vect2 <- c(3, 2, 2)
res <- caret::postResample(vect1, vect2)
rsq <- res[2]

Dit gebruikt echter de correlatie-kwadraatbenadering voor r-kwadraat zoals vermeld in een ander antwoord. Ik weet niet zeker waarom Max Kuhn niet alleen de conventionele 1-SSE/SST gebruikte.

caretheeft ook een R2()-methode, hoewel deze moeilijk te vinden is in de documentatie.

De manier om de normale determinatiecoëfficiëntvergelijkingte implementeren is:

preds <- c(1, 2, 3)
actual <- c(2, 2, 4)
rss <- sum((preds - actual) ^ 2)
tss <- sum((actual - mean(actual)) ^ 2)
rsq <- 1 - rss/tss

Niet slecht natuurlijk om met de hand te coderen, maar waarom is er geen functie voor in een taal die voornamelijk voor statistieken is gemaakt? Ik denk dat ik de implementatie van R ^ 2 ergens moet missen, of niemand geeft er genoeg om om het te implementeren. De meeste implementaties, zoals deze, lijken voor gegeneraliseerde lineaire modellen.


Antwoord 5, autoriteit 7%

Hier is de eenvoudigste oplossing gebaseerd op [https://en.wikipedia.org/wiki/Coefficient_of_determination ]

# 1. 'Actual' and 'Predicted' data
df <- data.frame(
  y_actual = c(1:5),
  y_predicted  = c(0.8, 2.4, 2, 3, 4.8))
# 2. R2 Score components
# 2.1. Average of actual data
avr_y_actual <- mean(df$y_actual)
# 2.2. Total sum of squares
ss_total <- sum((df$y_actual - avr_y_actual)^2)
# 2.3. Regression sum of squares
ss_regression <- sum((df$y_predicted - avr_y_actual)^2)
# 2.4. Residual sum of squares
ss_residuals <- sum((df$y_actual - df$y_predicted)^2)
# 3. R2 Score
r2 <- 1 - ss_residuals / ss_total

Antwoord 6, autoriteit 5%

Ik weet niet zeker waarom dit niet rechtstreeks in R is geïmplementeerd, maar dit antwoord is in wezen hetzelfde als dat van Andrii en Wordsforthewise, ik heb het voor het gemak gewoon in een functie veranderd als iemand het net als ik gebruikt.

r2_general <-function(preds,actual){ 
  return(1- sum((preds - actual) ^ 2)/sum((actual - mean(actual))^2))
}

Other episodes