25

我在我的代码中使用,colSums但我还需要总和旁边的标准偏差。我在互联网上搜索,发现此页面仅包含:

colSums
colMeans

http://stat.ethz.ch/R-manual/R-devel/library/base/html/colSums.html

我试过这个:

colSd

但我收到了这个错误:

Error: could not find function "colSd"

除了标准偏差,我怎么能做同样的事情:

colSd

这是代码:

results <- colSums(x,na.rm=TRUE)#### here I want colsd
4

8 回答 8

27

我想提供第四种(与@Thomas 非常相似)方法和一些基准测试:

library("microbenchmark")
library("matrixStats")

colSdApply <- function(x, ...)apply(X=x, MARGIN=2, FUN=sd, ...)
colSdMatrixStats <- colSds

colSdColMeans <- function(x, na.rm=TRUE) {
  if (na.rm) {
    n <- colSums(!is.na(x)) # thanks @flodel
  } else {
    n <- nrow(x)
  }
  colVar <- colMeans(x*x, na.rm=na.rm) - (colMeans(x, na.rm=na.rm))^2
  return(sqrt(colVar * n/(n-1)))
}

colSdThomas <- function(x)sqrt(rowMeans((t(x)-colMeans(x))^2)*((dim(x)[1])/(dim(x)[1]-1)))

m <- matrix(runif(1e7), nrow=1e3)

microbenchmark(colSdApply(m), colSdMatrixStats(m), colSdColMeans(m), colSdThomas(m))

# Unit: milliseconds
#                 expr      min       lq   median       uq      max neval
#        colSdApply(m) 435.7346 448.8673 456.6176 476.8373 512.9783   100
#  colSdMatrixStats(m) 344.6416 357.5439 383.8736 389.0258 465.5715   100
#     colSdColMeans(m) 124.2028 128.9016 132.9446 137.6254 172.6407   100
#       colSdThomas(m) 231.5567 240.3824 245.4072 274.6611 307.3806   100


all.equal(colSdApply(m), colSdMatrixStats(m))
# [1] TRUE
all.equal(colSdApply(m), colSdColMeans(m))
# [1] TRUE
all.equal(colSdApply(m), colSdThomas(m))
# [1] TRUE
于 2013-07-09T15:00:25.780 回答
7

colSds并且是matrixStats 包rowSds中许多相似函数中的两个

于 2013-07-09T13:57:55.670 回答
6

这是计算列的标准偏差的最快和最短的方法:

sqrt(diag(cov(data_matrix)))

由于协方差矩阵的对角线由每个变量的方差组成,因此我们执行以下操作:

  • 使用计算协方差矩阵cov
  • 使用提取矩阵的对角线diag
  • 取对角线值的平方根,sqrt以获得标准偏差

我希望这会有所帮助:)

于 2018-01-23T05:38:12.173 回答
4

使用以下内容:

colSd <- function (x, na.rm=FALSE) apply(X=x, MARGIN=2, FUN=sd, na.rm=na.rm)
于 2013-07-09T13:44:30.437 回答
4

我相信我已经找到了一个更优雅的解决方案diag(sqrt(var(data)))

这对我来说是为了得到我每列的标准偏差。但是,它确实会计算一堆额外的不必要的协方差(及其平方根),因此它不一定是最有效的方法。但是,如果您的数据很小,则效果很好。

编辑:我刚刚意识到这sqrt(diag(var(data)))可能更有效,因为它更早地删除了不必要的协方差项。

于 2014-04-13T23:34:29.090 回答
4

我不知道这些是否特别快,但为什么不直接使用 SD 的公式:

x <- data.frame(y = rnorm(1000,0,1), z = rnorm(1000,2,3))

# If you have a population:
colsdpop <- function(x,...)
     sqrt(rowMeans((t(x)-colMeans(x,...))^2,...))
colsdpop(x)
sd(x$y); sd(x$z) # won't match `sd`

# If you have a sample:
colsdsamp <- function(x)
    sqrt( (rowMeans((t(x)-colMeans(x))^2)*((dim(x)[1])/(dim(x)[1]-1))) )
colsdsamp(x)
sd(x$y); sd(x$z) # will match `sd`

注意:示例解决方案不能NA很好地处理。人们可以在公式的最右边加入类似的东西apply(x,2,function(z) sum(!is.na(z)))来得到一个合适的分母,但它很快就会变得非常模糊。

于 2013-07-09T14:43:18.547 回答
2

我通常用以下方式做 sd 列apply

x <- data.frame(y = rnorm(20,0,1), z = rnorm(20,2,3))

> apply(x, 2, sd)
        y         z 
0.8022729 3.4700314 

核实:

> sd(x$y)
[1] 0.8022729

> sd(x$z)
[1] 3.470031

您也可以dplyr轻松地做到这一点:

library(dplyr)
library(magrittr) # for pipes

> x %>% summarize_all(.,sd)
          y        z
1 0.8022729 3.470031
于 2019-10-10T03:59:08.807 回答
0

您可以只使用应用功能

all.sd <- 应用(数据,2,sd)

于 2019-11-03T15:44:06.067 回答