用于计算R中的R2(R平方)的函数

Esm*_*me_ 16 statistics r function

我有一个带有观察和建模数据的数据框,我想计算R2值.我希望有一个我可以为此调用的函数,但找不到它.我知道我可以写自己的并应用它,但我错过了一些明显的东西吗?我想要类似的东西

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

R2 <- rsq(df)
# 0.85
Run Code Online (Sandbox Code Playgroud)

李哲源*_*李哲源 36

你需要一些统计知识才能看到这一点.两个向量之间的R平方只是它们相关性的平方.所以你可以定义你的功能:

rsq <- function (x, y) cor(x, y) ^ 2
Run Code Online (Sandbox Code Playgroud)

Sandipan的答案将返回完全相同的结果(参见下面的证据),但是它看起来更具可读性(由于明显$r.squared).


我们来统计一下

基本上,我们拟合的线性回归yx,并计算回归平方和的比率,以总平方和.

引理1:回归y ~ x相当于y - mean(y) ~ x - mean(x)

引理1

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

引理2

引理3:R.square = cor(x,y)^ 2

引理3


警告

两个任意向量之间的R平方xy(相同长度)只是它们线性关系的良好度量.三思!对于任何恒定的移位,R之间的平方x + ay + b相同.因此,它对"预测的良好性"是一种微弱甚至无用的衡量标准.请改用MSE或RMSE:ab

我同意42的评论:

通过与回归函数相关联的汇总函数报告R平方.但只有当这种估计在统计上是合理的时候.

R平方可以是"适合度"的衡量标准(但不是最佳).但没有理由认为它可以衡量样本外预测的优点.如果将数据拆分为训练和测试零件并在训练零件上拟合回归模型,则可以在训练零件上获得有效的R平方值,但是您无法合理地计算测试零件上的R平方.有些人这样做了,但我不同意.

这是一个非常极端的例子:

preds <- 1:4/4
actual <- 1:4
Run Code Online (Sandbox Code Playgroud)

这两个向量之间的R平方为1.当然,一个只是另一个的线性重新缩放,因此它们具有完美的线性关系.但是,你真的认为这preds是一个很好的预测actual吗?


回答这句话

感谢您的意见1,2你的细节的答案.

你可能误解了这个程序.由于两个矢量xy,我们首先拟合回归线y ~ x然后计算平方和总平方的回归之和.看起来你跳过这个回归步骤直接进入平方计算的总和.这是错误的,因为平方和的分区不成立,你无法以一致的方式计算R平方.

如您所示,这只是计算R平方的一种方法:

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
Run Code Online (Sandbox Code Playgroud)

但还有另一个:

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

此外,您的公式可以给出负值(正如" 警告"部分中所述,正确的值应为1 ).

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
Run Code Online (Sandbox Code Playgroud)

最后的评论

当我在2年前发布我的初步答案时,我从未预料到这个答案最终会如此长.但是,鉴于这个主题的高度观点,我觉得有必要添加更多的统计细节和讨论.我不想误导人们,因为他们可以很容易地计算出R平方,他们可以在任何地方使用R平方.

  • 在多元线性回归中,R 平方是响应向量和拟合值之间的平方相关性。试试 `model &lt;- lm(trees); cor(trees[[1]], model$fitted.values) ^ 2`。将此与 `summary(model)$r.squared` 进行比较 (3认同)
  • 为了实现这一点,必须满足一些假设:http://www.win-vector.com/blog/2011/11/correlation-and-r-squared/ 我想将它用于 KNN,但我'我不确定这些假设是否成立。必须检查这是否实际上与传统计算的 R^2 相同 (2认同)
  • 相关^ 2方法和传统1-SSE/SST的答案是不一样的.在我使用的例子中,我得到了来自corr ^ 2的"0.756388"和来自正常r ^ 2等式的"0.7531449".差别很小,但仍然可能会为超参数选择等建模. (2认同)
  • 这个答案似乎是错误的。您指出:“两个向量之间的 R 平方就是它们相关性的平方”。除非我弄错了,否则这只在具有估计截距的最小二乘线性回归的情况下才是正确的。一般来说,Rsquared 的公式为“1 - 残差平方和 / 总平方和”。(是的,这可能会产生负面结果,这只是表明估计值比使用平均值作为预测更糟糕。) (2认同)

San*_*Dey 12

为什么不这样:

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

  • 这可行,但对于大型矩阵来说速度很慢:`lm()`(和`summary.lm()`)做了很多不必要的计算。有关更多信息,请参阅 /sf/ask/1779148941/ 。 (3认同)

wor*_*ise 6

这不是显而易见的事情,但是该caret软件包具有postResample()根据文档计算"性能估计的向量" 的函数."业绩估计"是

  • RMSE
  • Rsquared
  • 平均绝对误差(MAE)

并且必须从这样的矢量访问

library(caret)
vect1 <- c(1, 2, 3)
vect2 <- c(3, 2, 2)
res <- caret::postResample(vect1, vect2)
rsq <- res[2]
Run Code Online (Sandbox Code Playgroud)

然而,这是使用另一个答案中提到的r平方的相关平方近似.为什么他们不仅仅使用传统的1-SSE/SST超出了我的范围.

实现正态确定系数方程的方法是:

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
Run Code Online (Sandbox Code Playgroud)

手动编码当然不是太糟糕,但为什么在主要用于统计的语言中没有它的功能呢?我想我仍然错过了某个地方R ^ 2的实现.


小智 5

您还可以将摘要用于线性模型:

summary(lm(obs ~ mod, data=df))$r.squared 
Run Code Online (Sandbox Code Playgroud)


And*_*rii 5

这是基于 [ 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
Run Code Online (Sandbox Code Playgroud)


Joe*_*moe 5

不知道为什么这没有直接在 R 中实现,但这个答案本质上与 Andrii 和 Wordsforthewise 相同,如果有人像我一样经常使用它,我只是为了方便起见将其变成一个函数。

r2_general <-function(preds,actual){ 
  return(1- sum((preds - actual) ^ 2)/sum((actual - mean(actual))^2))
}
Run Code Online (Sandbox Code Playgroud)