2016-08-16 73 views
-1

給定一個有序向量vec <- c(1, 4, 6, 3, 2, 7),我想計算每個元素ivec以前元素的加權平均值,其中權重是與元素i之間的距離的倒數。R:計算一個有序向量的先前元素

該功能應繼續如下。

  • 對於第一個元素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))) 
    } 
} 
+0

請顯示您的努力以及它出錯的地方。 –

+0

可能的重複:http://stackoverflow.com/q/743812/903061 - 雖然它不是專門針對* weighted *移動平均值,但許多方法(例如'RcppRoll')都提供了該功能。 – Gregor

+0

[Here's another](http://stackoverflow.com/q/8720055/903061),雖然看起來有些過時。 – Gregor

回答

2

這裏有一個天真的實現。創建一個能夠完成你所說的功能;唯一的「聰明」的事情是使用功能seq_len()而不是1:我生成索引

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

,然後在sapply

sapply(seq_along(vec), fun, vec) 

使用它這是不夠好 - NaN的作爲第一個元素,而不是NA,但在事實之後很容易糾正(或者在概念上被接受爲正確答案)。它也比你的解決方案更好,但仍然'使用循環' - 結果向量的管理由sapply()完成,而不是在你必須自己管理它的循環中完成。特別是你的'複製和追加'方法在性能方面非常糟糕,每次通過循環複製現有的結果。最好預先分配合適長度的結果向量result = numeric(length(vec)),然後填寫它result[[i]] = ...,最好還是讓sapply()爲你做正確的事!

問題是天真的實現按比例縮放 - 您沿着vec傳遞每個元素,然後對每個元素進行第二次傳遞以計算加權平均值,因此有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()獲得的累計權重,而不是個人的權重,即,只要返回一個向量作爲x,其中第i個元素是加權平均到這一點

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

你想要的東西有點不同

myweighted.mean <- function(x) 
    c(NA, cumweighted.mean(head(x, -1), head(seq_along(x), - 1))) 

這使得單次通過數據是線性的(至少在理論上)。