求和,然后取R中的平均值

时间:2018-11-02 05:41:47

标签: r matrix cumsum

我想计算第一个(n-1) columns的累积和(如果我们有n列矩阵),然后取平均值。我创建了一个样本矩阵来执行此任务。我有以下矩阵

ma = matrix(c(1:10), nrow = 2, ncol = 5)
ma
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10

我想找到以下内容

ans = matrix(c(1,2,2,3,3,4,4,5), nrow = 2, ncol = 4)
ans
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    2    3    4    5

以下是我的r函数。

ColCumSumsAve <- function(y){
  for(i in seq_len(dim(y)[2]-1)) {
    y[,i] <- cumsum(y[,i])/i
  }
}
ColCumSumsAve(ma)

但是,当我运行上面的函数时,它不会产生任何输出。代码中有任何错误吗?

谢谢。

4 个答案:

答案 0 :(得分:3)

有几个错误。

解决方案

这是我测试过的并且有效的方法:

colCumSumAve <- function(m) {
  csum <- t(apply(X=m, MARGIN=1, FUN=cumsum))
  res <- t(Reduce(`/`, list(t(csum), 1:ncol(m))))
  res[, 1:(ncol(m)-1)]
}

使用以下方法进行测试:

> colCumSumAve(ma)
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    2    3    4    5

这是正确的。

说明:

colCumSumAve <- function(m) {
  csum <- t(apply(X=m, MARGIN=1, FUN=cumsum)) # calculate row-wise colsum
  res <- t(Reduce(`/`, list(t(csum), 1:ncol(m))))
  # This is the trickiest part.
  # Because `csum` is a matrix, the matrix will be treated like a vector 
  # when `Reduce`-ing using `/` with a vector `1:ncol(m)`.
  # To get quasi-row-wise treatment, I change orientation
  # of the matrix by `t()`. 
  # However, the output, the output will be in this transformed
  # orientation as a consequence. So I re-transform by applying `t()`
  # on the entire result at the end - to get again the original
  # input matrix orientation.
  # `Reduce` using `/` here by sequencial list of the `t(csum)` and
  # `1:ncol(m)` finally, has as effect `/`-ing `csum` values by their
  # corresponding column position.
  res[, 1:(ncol(m)-1)] # removes last column for the answer.
  # this, of course could be done right at the beginning,
  # saving calculation of values in the last column,
  # but this calculation actually is not the speed-limiting or speed-down-slowing step
  # of these calculations (since this is sth vectorized)
  # rather the `apply` and `Reduce` will be rather speed-limiting.
}

好吧,那我可以做:

colCumSumAve <- function(m) {
  csum <- t(apply(X=m[, 1:(ncol(m)-1)], MARGIN=1, FUN=cumsum))
  t(Reduce(`/`, list(t(csum), 1:ncol(m))))
}

或:

colCumSumAve <- function(m) {
  m <- m[, 1:(ncol(m)-1)] # remove last column
  csum <- t(apply(X=m, MARGIN=1, FUN=cumsum))
  t(Reduce(`/`, list(t(csum), 1:ncol(m))))
}

那么,这实际上是更优化的解决方案。

原始功能

您的原始函数仅在for循环中进行赋值,并且不返回任何内容。 因此,我首先将您的输入复制到res,用您的for循环进行处理,然后返回res

ColCumSumsAve <- function(y){
  res <- y
  for(i in seq_len(dim(y)[2]-1)) {
    res[,i] <- cumsum(y[,i])/i
  }
  res
}

但是,这给出了:

> ColCumSumsAve(ma)
     [,1] [,2]     [,3] [,4] [,5]
[1,]    1  1.5 1.666667 1.75    9
[2,]    3  3.5 3.666667 3.75   10

问题在于,矩阵中的cumsum是按列方向而不是按行计算的,因为它像对待向量一样对待矩阵(逐列穿过矩阵)。

已纠正的原始功能

经过一番挑剔,我意识到,正确的解决方案是:

ColCumSumsAve <- function(y){
  res <- matrix(NA, nrow(y), ncol(y)-1) 
  # create empty matrix with the dimensions of y minus last column
  for (i in 1:(nrow(y))) {           # go through rows
    for (j in 1:(ncol(y)-1)) {       # go through columns
      res[i, j] <- sum(y[i, 1:j])/j  # for each position do this
    }
  }
  res   # return `res`ult by calling it at the end!
}

进行测试:

> ColCumSumsAve(ma)
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    2    3    4    5

注意:dim(y)[2]ncol(y)-和dim(y)[1]nrow(y)- 而不是seq_len()1:较短,我想甚至更快。

注意:我首先给出的解决方案将更快,因为它使用了apply,矢量化的cumsumReduce。 -R中的for循环较慢。

最新说明:不确定第一个解决方案是否更快。从R-3.x开始,看来for循环更快。 Reduce将成为限速功能,有时甚至会非常慢。

答案 1 :(得分:2)

k <- t(apply(ma,1,cumsum))[,-ncol(k)]
for (i in 1:ncol(k)){
  k[,i] <- k[,i]/i
}
k

这应该有效。

答案 2 :(得分:2)

您只需要rowMeans

nc <- 4
cbind(ma[,1],sapply(2:nc,function(x) rowMeans(ma[,1:x])))
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    2    3    4    5

答案 3 :(得分:1)

这是我的做法

> t(apply(ma, 1, function(x) cumsum(x) / 1:length(x)))[,-NCOL(ma)]
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    2    3    4    5

这将cumsum函数逐行应用于矩阵ma,然后除以正确的长度以获得平均值(cumsum(x)1:length(x)将具有相同的长度)。然后只需用t转置,并用[,-NCOL(ma)]删除最后一列。

函数没有输出的原因是因为您没有返回任何东西。您应该以{{1​​}}结束函数,或者按照Marius的建议以return(y)结尾。无论如何,您的函数似乎都无法给您正确的响应。