2016-08-16 25 views
-1

ベクトルがvec <- c(1, 4, 6, 3, 2, 7)の場合、iがからの距離の逆数である前の要素の加重平均であるvecを計算します。R:順序付きベクトルの前の要素を計算する

この機能は次のように進められます。

  • 最初の要素の場合、1は、NA(前の要素なし)を返す必要があります。
  • 2番目の要素の場合、4は、1を返す必要があります。
  • 第3要素6については、weighted.mean(x = c(1,4), w = c(1,2))を返す必要があります。第4要素3について
  • weighted.mean(x = c(1,4,6), w = c(1,2,3))

を返す必要が得られたベクターresultlength(result) == length(vec)c(NA, 1, 3, 4.5, 3.9, 3.266667)であるべきです。

UPDATE: は、私ははっきりとループ

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 - 特に、*加重*移動平均ではありませんが、メソッドの多く(例: 'RcppRoll')はその機能を提供します。 – Gregor

+0

[これは別です](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に沿って各要素を処理し、次に各要素に対して加重平均を計算するために2番目のパスを作成するため、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()を使用します、あなたは少し違ったものにたい

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

i番目の要素は、その点に加重平均をアップしているx、限りベクトルを返す

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

これは、1回通過しますデータは線形にスケーリングされます(少なくとも理論上は)。

関連する問題