2016-11-24 10 views
0

変数のストックエフェクトを1つの列に作成する次の関数があります。変数がColumnAの値をとる列Bの値を作成し、B列の前の観察から(例えば0.5のような)キャリーオーバー他の列の値に応じて行にR関数を適用

constructZ <- function(lag, N) { 
    r <- lag^(seq_len(N)-1) 
    m <- matrix(rep(r,N),nrow=N) 
    z <- matrix(0,nrow=N,ncol=N) 
    z[lower.tri(z,diag=TRUE)] <- m[row(m) <= (N+1-col(m))] 
    z 
} 

を追加私の問題は、私はパネルデータセットを持っているということになりました多くの異なるケースについて1つの列で観察しています。それぞれのケースには特定のインジケータ(数値)があります。データは次のようになります。

ColumnA  Indicator   Time 
1   1     1 
0   1     2 
0   1     3 
4   2     1 
5   2     2 
0   2     3 
4   3     1 
0   3     2 
2   3     3 

すべての観測(時間)に対して各ケース(インジケータ)に関数を適用します。

どのようにこれを達成するためのアイデアですか?出力は次のようになります。

ColumnA  Indicator   Time   ColumnB 
    1   1     1   1 
    0   1     2   0.5 
    0   1     3   0.25 
    4   2     1   4 
    5   2     2   7 
    0   2     3   3.5 
    4   3     1   4 
    0   3     2   2 
    2   3     3   3 

ご協力いただきありがとうございます。

事前に感謝します。

+2

期待される出力を得るためにlagとNの値はどのようになりますか? – akrun

+0

私が理解したかどうか教えてください:columnB [i] = columnA + columnB [i-1] *何か? :) – Ale

答えて

0

ここに私のコードです。

library(dplyr) # Optional, but makes code cleaner 
raw = data.frame(ColumnA = 
        c(1, 0, 0, 4, 5, 0, 4, 0, 2), 
       Indicator = 
        rep(x = 1:3, each = 3), 
       Time = 1:3) 
factor = 0.5 
loop = function(vec) { 
    length = length(x = vec) 
    if (length == 1) { 
    return(vec) 
    } 
    if (length == 2) { 
    return(vec + c(0, vec[2] * factor)) 
    } 
    for (idx in 2:length) { 
    vec[idx] = vec[idx] + vec[idx - 1] * factor 
    } 
    return(vec) 
} 
output = raw %>% 
    mutate(ColumnB = 
      tapply(X = ColumnA, 
        INDEX = Indicator, 
        FUN = loop) %>% 
    unlist()) 
output 
0

ここでは、ループフリー/関数型プログラミングの代替ソリューションを示します。我々はベクトル内のアイテムのすべてのペアにバイナリ関数を適用するReduce()関数を使用します。

たとえば、Reduce(`+`, xs)は、ベクトルの値の合計を計算します。 accumulate = TRUEを設定すると、ローリング/累積合計が得られます。

Reduce(`+`, 1:6) 
#> [1] 21 

# What Reduce is doing here, basically 
((((((1) + 2) + 3) + 4) + 5) + 6) 
#> [1] 21 

# Keep each intermediate sum 
Reduce(`+`, 1:6, accumulate = TRUE) 
#> [1] 1 3 6 10 15 21 

(purrrパッケージが異なる機能にこれらの2つの動作を分離:reduce()accumulate()を)

我々はキャリーオーバー/スケーリング機能を実装するためにReduce()を使用することができます。まず、値のペアで動作する関数を定義し、Reduce()を使用してローリングバージョンを実行します。

rolling_scale <- function(xs, scale_factor) { 
    scale_pair <- function(x1, x2) x2 + scale_factor * x1 
    Reduce(scale_pair, xs, accumulate = TRUE) 
} 

rolling_scale(c(4, 5, 0), .5) 
#> [1] 4.0 7.0 3.5 

ここで、dplyrを使用して、この指標を各指標グループに適用することができます。

library(dplyr) 

raw <- data.frame(
    ColumnA = c(1, 0, 0, 4, 5, 0, 4, 0, 2), 
    Indicator = rep(x = 1:3, each = 3), 
    Time = 1:3) 

raw %>% 
    group_by(Indicator) %>% 
    mutate(ColumnB = rolling_scale(ColumnA, .5)) %>% 
    ungroup() 
#> # A tibble: 9 × 4 
#> ColumnA Indicator Time ColumnB 
#>  <dbl>  <int> <int> <dbl> 
#> 1  1   1  1 1.00 
#> 2  0   1  2 0.50 
#> 3  0   1  3 0.25 
#> 4  4   2  1 4.00 
#> 5  5   2  2 7.00 
#> 6  0   2  3 3.50 
#> 7  4   3  1 4.00 
#> 8  0   3  2 2.00 
#> 9  2   3  3 3.00 
関連する問題