【问题标题】:Why does var act like cov in R?为什么 var 在 R 中表现得像 cov?
【发布时间】:2013-03-27 03:44:52
【问题描述】:

很抱歉问这个问题......这肯定是一个常见问题解答,而且这是一个愚蠢的问题,但它一直困扰着我。假设我想获取数据框中每个数字列的方差,例如

df <- data.frame(x=1:5,y=seq(1,50,10))

当然,我试试

var(df)

而不是给我我希望的东西,就像

  x    y
2.5  250

我明白了

     x   y
x  2.5  25
y 25.0 250

在对角线上有方差,在其他位置有协方差。当我查找 help(var) 并读到“var 只是 cov 的另一个接口”时,这是有道理的。当然,方差是变量与其自身之间的协方差。输出有点混乱,但我可以沿对角线读取,或者使用diag(var(df))sapply(df, var)lapply(df, var) 或通过在df$xdf$y 上反复调用var 来生成方差。

但是为什么呢?方差是一种常规的、基本的描述性统计数据,仅次于均值。将它应用于数据框的列不应该是完全和完全微不足道的吗?当我只要求方差时,为什么要给我协方差?只是好奇。感谢任何关于此的 cmets。

【问题讨论】:

  • This 问题也可能有助于阅读。

标签: r


【解决方案1】:

惯用的方法是

sapply(df, var)

var 有一个data.frames 的方法, 通过强制转换为matrix 来处理data.frames

Variance 是常规的基本描述性统计量,协方差和相关性也是如此。它们都是相互关联且有趣的,特别是如果您打算使用线性模型。

你总是可以创建你自己的函数来执行你想要的

Var  <- function(x,...){
  if(is.data.frame(x)) {
   return(sapply(x, var,...))} else { return(var(x,...))}
}

【讨论】:

  • var 有数据帧的方法可能会有点混乱;它不是通常的 R 意义上的方法(S3 或 S4 方法)。数据帧被简单地转换为矩阵,然后应用cov
  • 谢谢 mnel、GavinSimpson、SimonO101。这些都是非常有帮助的答案,joran 的链接也是如此——因此,尽管我已将它们全部投了赞成票,但我不愿意将其中一个标记为 the 答案。我明白了。
【解决方案2】:

这在?var中有记载,即:

Description:

     ‘var’, ‘cov’ and ‘cor’ compute the variance of ‘x’ and the
     covariance or correlation of ‘x’ and ‘y’ if these are vectors.  If
     ‘x’ and ‘y’ are matrices then the covariances (or correlations)
     between the columns of ‘x’ and the columns of ‘y’ are computed.

“矩阵”中的文本表示"matrix""data.frame" 类的对象。

var 没有传统意义上的数据帧方法。 var 只是通过as.matrix 将输入数据帧强制转换为一个矩阵,然后在该矩阵上调用cov

在回答为什么的问题时,我猜方差与协方差的概念密切相关,并且为了保持代码简单,R Core 为类矩阵对象的协方差编写了一个实现,并将其用于方差因为这是您最有可能从矩阵中得到的东西。

或者更简洁;这就是 R Core 实现这一点的方式。学会忍受它。 :-)

另请注意,R 正在远离像 meansd 这样的函数对数据框的组件(列)进行操作。如果你想应用这些函数中的任何一个,包括var,你需要调用类似:

apply(foo, 2, mean) ## for matrices
sapply(foo, mean) ## for data frames

或更快的特定替代方案

colMeans(foo)

在这种情况下,我怀疑diag(var(df)) 将是获取方差的最有效方法,而不是通过apply 系列函数之一反复调用var @987654337 @ 不太可能比 sapply(df, var) 快,因为前者必须计算所有协方差以及方差。

【讨论】:

  • +1 我已经编辑了我的回复,指出缺少常规的method
  • 我很好奇 diag(var(df)) 或 sapply(df, var) 是否会更快。在这个例子中:df &lt;- data.frame(x=rnorm(4*10^7), y=rbinom(4*10^7, 100, .5)),sapply(df,var) 在操作过程中大约需要 1.8 秒,并将 R 的 RAM 使用量从大约 1GB 增加到 1.7GB,而sapply(diag(var(df))) 大约需要 4.5 秒,并且在操作过程中将 RAM 从 1GB 增加到大约 2.5GB操作(R 2.15.0,MacBook Air 1.6GHz Intel Core 2 Duo,4GB RAM,OS X 10.6.8)。
  • @Mars 不,你错了。整个电话是diag(var(df));你不sapply它。正如您在问题var(df) 中显示的那样,返回df 的整个方差-协方差矩阵。您想要的位在对角线上,因此我们使用diag() 提取它们。无论如何,我现在意识到这种方式也计算协方差,因此可能比sapply 版本慢。
  • 抱歉,打错了。我确实在没有sapply 的情况下运行了diag(var(df))(我相信这是行不通的)。
【解决方案3】:

@GavinSimpson 已涵盖您的实际答案。对于var,您也可以使用:

sd(df)^2
# x     y 
# 2.5 250.0 

通过这样做,您将看到 @GavinSimpson 对 R 的意义“不再让 meansd 等函数对数据框的组件(列)进行操作”。已弃用意味着该功能可能会随着即将发生的 R 版本更改而停用,如果您不注意警告并进行适当更改,您的代码可能会中断:

警告信息: sd() 已弃用。 使用 sapply(*, sd) 代替。

所以我们可以使用:

sapply(df,sd)^2
# x     y 
# 2.5 250.0 

这给了我们完全相同的结果。

但是,这样做有点愚蠢,因为您实际上是在每一列上调用(sqrt(var(x, na.rm = na.rm)))^2!相反,正如@mnel 所建议的那样,sapply( df , var) 是您应该如何获得每个列向量的方差。

【讨论】:

    猜你喜欢
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多