【问题标题】:why does sd in R return a vector for matrix input, and what can I do about it?为什么 R 中的 sd 返回矩阵输入的向量,我该怎么办?
【发布时间】:2011-08-21 03:59:19
【问题描述】:

我有点困惑,为什么 R 中的 sd 函数会返回一个矩阵输入数组(我想保持向后兼容性,它总是会)。这对我来说是非常奇怪的行为:

#3d input, same same
print(length(mean(array(rnorm(60),dim=c(3,4,5)))))
print(length(sd(array(rnorm(60),dim=c(3,4,5)))))
#1d input, same same
print(length(mean(array(rnorm(60),dim=c(60)))))
print(length(sd(array(rnorm(60),dim=c(60)))))
#2d input, different!
print(length(mean(array(rnorm(60),dim=c(12,5)))))
print(length(sd(array(rnorm(60),dim=c(12,5)))))

我明白了

[1] 1
[1] 1
[1] 1
[1] 1
[1] 1
[1] 5

当输入是二维数组时,sd 的行为与mean 的行为不同(显然仅在这种情况下!)考虑一下,这个失败的函数重新缩放 k 维数组的每一列标准差:

re.scale <- function(x) {
    #rescale by the standard deviation of each column
    scales <- apply(x,2,sd)
    ret.val <- sweep(x,2,scales,"/")
}

#this works just fine
x <- array(rnorm(60),dim=c(12,5))
y <- re.scale(x)

#this throws a warning
x <- array(rnorm(60),dim=c(3,4,5))
y <- re.scale(x)

如果没有这种奇怪的行为,是否有其他功能可以替换 sd?如何正确地写re.scale?还是按列的 Z 分数函数?

【问题讨论】:

  • 为什么投反对票?这是一个非常合理、清晰的问题。
  • 问题应该可能反映了 R >= 3.0 中的行为变化(见下面@Yoshiyuki 的回答)。

标签: r


【解决方案1】:

它的行为就像 sd 帮助页面中的文档。在最顶部它宣布:

"如果 x 是矩阵或数据框,则返回列的标准差向量。"

注意它并没有说包含数组,所以只包含二维数组。如果你想停止这种行为,那么只需用 c() 从中制作一个向量:

 sd( c(array(rnorm(60),dim=c(12,5))) )
 # [1] 0.9505643

我看到您添加了对 z 列分数的请求。试试这个矩阵:

colMeans(x)/sd(x)

这适用于数组(尽管“列”的定义可能需要澄清:

apply(x, 2:3, mean)/apply(x, 2:3, sd)   # will generalize to higher dimensions

【讨论】:

  • 是的,我已阅读文档。我的问题是为什么会做出这个选择?它似乎完全是任意的并且不匹配,例如,mean.
  • 虽然 var 和 sd 具有相同的行为 w.r.t.列。我确实理解为什么没有对数组进行列处理。当然,有一个非常好的函数 colMeans,用于获取列均值向量。我怀疑 S 语言(这是 R 所依赖的语法标准)的任何作者都可能正在阅读此交流。如果我的回答确实令人满意,您需要询问 John Chambers 或 Trevor Hastie。
  • 这是因为矩阵或数据框的列通常是感兴趣的变量的值。然后 sd(matrix) 会告诉您变量的 sd - 如果它按行进行,那么您将获取不相关事物的 sd。那么,你说,为什么不意味着(矩阵)给列的意思?好吧, mean(data.frame) 确实如此,所以这是一个线索,也许你应该使用数据帧。但是对于矩阵,我认为它只是在开发一种特定领域语言的早期阶段做出的一个糟糕的决定,当时没有多少人使用......
  • FWIW,MatLab 也这样做,所以很明显“有人”认为这是个好主意。只要做 sd(as.vector(your_matrix)) 一切都很好。
  • 实际上,Matlab 在 meanstd 之间有一个一致的 API:它沿给定维度应用运算符(默认为第一个非平凡维度)。它从不将所有数据汇集在一起​​。 Matlab 中的“Z-score-by-dimension”运算符非常简单:@(x,varargin)(bsxfun(@rdivide,bsxfun(@minus,x,mean(x,varargin{:})),std(x,varargin{:})) 不幸的是,在 R 中如何做到这一点还不太清楚。
【解决方案2】:

sd的动作发生了变化:

1。 2.13.2(2011-09-30) 及更早版本

> set.seed(1)
> sd(array(rnorm(60),dim=c(12,5))) 
[1] 0.8107276 1.1234795 0.7925743 0.6186082 0.9464160

说明

此函数计算 x 中值的标准差。如果 na.rm 为 TRUE,然后在计算之前删除缺失值 收益。 如果 x 是 矩阵或数据框,则为标准向量 返回列的偏差


2。 R 版本 2.14.0(2011-10-31) - 2.15.3(2013-03-01)

> set.seed(1)
> sd(array(rnorm(60),dim=c(12,5))) 
[1] 0.8107276 1.1234795 0.7925743 0.6186082 0.9464160
 WARNING:
sd(<matrix>) is deprecated.
 Use apply(*, 2, sd) instead. 

详情

在 R 2.14.0 之前,sd(dfrm) 直接用于 data.frame dfrm。现在已弃用,您应该使用 sapply(dfrm, sd)。


3。 R 版本 3.0.0 (2013-04-03) 及更高版本

> sd(array(rnorm(60),dim=c(12,5))) 
[1] 0.8551688
>
(no WARNIG)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多