web-dev-qa-db-fra.com

Fonction pour calculer R2 (R-carré) dans R

J'ai une base de données avec des données observées et modélisées, et j'aimerais calculer la valeur R2. Je m'attendais à ce qu'il y ait une fonction que je pourrais appeler pour cela, mais je ne peux pas en trouver une. Je sais que je peux écrire le mien et l'appliquer, mais est-ce qu'il me manque quelque chose d'évident? Je veux quelque chose comme

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

R2 <- rsq(df)
# 0.85
11
Esme_

Vous avez besoin d'un peu de connaissances statistiques pour voir cela. R carré entre deux vecteurs est juste le carré de leur corrélation . Ainsi, vous pouvez définir votre fonction comme:

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

Réponse de Sandipan vous retournera exactement le même résultat (voir la preuve suivante), mais dans l'état actuel des choses, il semble plus lisible (en raison de la $r.squared évidente).


Faisons les statistiques

Fondamentalement, nous ajustons une régression linéaire de y sur x et calculons le rapport entre la somme des carrés de régression et la somme totale des carrés.

lemma 1: une régression y ~ x est équivalente à y - mean(y) ~ x - mean(x)

 lemma 1

lemme 2: beta = cov (x, y)/var (x)

 lemma 2

lemme 3: Rsquare = cor (x, y) ^ 2

 lemma 3


Attention

R carré entre deux vecteurs arbitraires x et y (de même longueur) est simplement une mesure de qualité de leur relation linéaire. Pensez-y à deux fois !! Les R carrés entre x + a et y + b sont identiques pour tout décalage constant a et b. Il s’agit donc d’une mesure faible, voire inutile, sur la "qualité de la prévision". Utilisez plutôt MSE ou RMSE:

Je suis d'accord avec le commentaire de 42 - :

Le R carré est rapporté par les fonctions récapitulatives associées aux fonctions de régression. Mais seulement quand une telle estimation est statistiquement justifiée. 

R carré peut être une mesure (mais pas la meilleure) de la "qualité de l'ajustement". Mais rien ne justifie qu'il puisse mesurer le bien-fondé d'une prévision hors échantillon. Si vous divisez vos données en parties d'apprentissage et de test et adaptez un modèle de régression au modèle d'apprentissage, vous pouvez obtenir une valeur de R au carré valide sur la partie d'apprentissage, mais vous ne pouvez pas légitimement calculer un R au carré sur la partie de test. Certaines personnes ont fait cela , mais je ne suis pas d'accord avec ça.

Voici un exemple très extrême:

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

Le R au carré entre ces deux vecteurs est 1. Oui bien sûr, l’un n’est qu’une remise à l’échelle linéaire de l’autre, de sorte qu’ils ont une relation linéaire parfaite. Mais pensez-vous vraiment que la variable preds est une bonne prédiction sur actual ??


En réponse à wordsforthewise

Merci pour vos commentaires 1 , 2 et votre réponse aux détails .

Vous avez probablement mal compris la procédure. Étant donné deux vecteurs x et y, nous ajustons d'abord une droite de régression y ~ x puis calculons la somme des carrés de régression et la somme totale des carrés. Il semble que vous sautiez cette étape de régression et que vous passiez directement à la somme du calcul carré. C'est faux, car la partition de la somme des carrés ne tient pas et vous ne pouvez pas calculer R au carré de manière cohérente.

Comme vous l'avez démontré, ce n'est qu'un moyen de calculer R au carré:

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

Mais il y en a un autre:

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

En outre, votre formule peut donner une valeur négative (la valeur appropriée doit être 1, comme indiqué ci-dessus dans la section Avertissement.).

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

Remarque finale

Je ne m'étais jamais attendu à ce que cette réponse soit si longue quand j'ai posté ma réponse initiale il y a 2 ans. Cependant, étant donné les vues élevées de ce fil, je me sens obligé d'ajouter plus de détails statistiques et de discussions. Je ne veux pas induire en erreur les gens qui, juste parce qu'ils peuvent calculer un R carré si facilement, peuvent utiliser R au carré partout.

19
李哲源

Pourquoi pas ceci:

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

Ce n'est pas quelque chose d'évident, mais le paquetage caret a une fonction postResample() qui va calculer "Un vecteur d'estimations de performances" selon documentation . Les "estimations de performance" sont 

  • RMSE
  • Rsquared
  • erreur absolue moyenne (MAE)

et doivent être accessibles à partir du vecteur comme celui-ci

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

Cependant, cela utilise l'approximation au carré de la corrélation pour le r-carré, comme mentionné dans une autre réponse. Pourquoi ils n’ont pas simplement utilisé le 1-SSE/SST conventionnel me dépasse.

La manière de mettre en œuvre l'équation normale coefficient de détermination est la suivante:

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

Pas trop mal à coder à la main bien sûr, mais pourquoi n’y at-il pas de fonction pour cela dans un langage principalement conçu pour les statistiques? Je pense que l’application de R ^ 2 me manque encore quelque part.

5
wordsforthewise

Vous pouvez également utiliser le résumé pour les modèles linéaires:

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

Voici la solution la plus simple basée sur [ https://en.wikipedia.org/wiki/Coefficient_of_détermination]

# 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
0
andrii