R:计算有序向量的先前元素

时间:2016-08-16 16:31:16

标签: r vector algebra

给定一个有序向量vec <- c(1, 4, 6, 3, 2, 7),我想为i的每个元素vec计算前一个元素的加权平均值,其中权重是距元素的距离的倒数i

该功能应如下进行。

  • 对于第一个元素1,应返回NA(没有前一个元素)。
  • 对于第二个元素4,应返回1
  • 对于第三个元素6,应返回weighted.mean(x = c(1,4), w = c(1,2))
  • 对于第四个元素3,应返回weighted.mean(x = c(1,4,6), w = c(1,2,3))

生成的向量result应该是length(result) == length(vec)c(NA, 1, 3, 4.5, 3.9, 3.266667)

更新: 我明确表示不使用循环

result <- numeric()

for (i in 1:length(vec)) {
  if (i == 1) {
    result <-
      c(result, NA)
  } else {
    previous_elements <- vec[1:(i-1)]
    result <-
      c(result, 
        weighted.mean(x = previous_elements, w = 1:length(previous_elements)))
  }
}

1 个答案:

答案 0 :(得分:2)

这是一个天真的实施。创建一个完成你所说的功能;唯一聪明的&#39;事情是使用函数seq_len()而不是1:i来生成索引

fun = function(i, vec)
    weighted.mean(head(vec, i - 1), w=seq_len(i - 1))

然后在sapply中使用它

sapply(seq_along(vec), fun, vec)

这已经足够了 - NaN是第一个元素,而不是NA,但事实之后很容易纠正(或者在概念上被接受为正确的答案)。它也比你的解决方案更好,但仍然使用循环&#39; - 结果向量的管理由sapply()完成,而不是在您必须自己管理的循环中完成。特别是你的复制和追加&#39;方法在性能方面非常差,每次通过循环复制现有结果。最好预先分配适当长度result = numeric(length(vec))的结果向量,然后填充result[[i]] = ...,最好让sapply()为你做正确的事!

问题在于,天真的实现以二次方式进行缩放 - 您沿着vec传递以处理每个元素,然后为每个元素进行第二次传递以计算加权平均值,因此存在{{ 1}}计算。所以......

查看n (n - 1) / 2

weighted.mean

并使用> stats:::weighted.mean.default function (x, w, ..., na.rm = FALSE) { ## SNIP -- edited for brevity w <- as.double(w) if (na.rm) { i <- !is.na(x) w <- w[i] x <- x[i] } sum((x * w)[w != 0])/sum(w) } 代替cumsum()来获取累积权重,而不是单个权重,即,只要sum()返回一个向量,其中第i个元素是加权意味着到那时为止

x

你想要一些不同的东西

cumweighted.mean <- function(x, w) {
    ## handle NA values?
    w <- as.numeric(w)  # to avoid integer overflow
    cumsum(x * w)[w != 0] / cumsum(w)
}

这使得单次通过数据,因此线性扩展(至少在理论上)。