2017-08-17 20 views
0

我需要實現一個計數器,它根據某些條件將dec_cnt減1。我的數據框df實現遞減值的順序計數器

ID A 
    1 0 
    2 0 
    3 0 
    4 1 
    5 1 
    6 0 
    7 0 
    8 0 
    9 0 
10 0 
11 0 
12 0 
13 0 
14 0 
15 0 
16 -1 
17 1 
18 0 
19 1 
20 0 
21 -1 
22 0 
23 0 
24 -1 
25 0 
26 0 
27 0 
28 0 
29 0 
30 0 
31 0 
32 0 
33 0 
34 0 

的條件是
一個。計數器應的數據點,其中A==1 or -1和在ID 4開始遞減下一16值計數器,用於A == 1例如值開始,所以從ID == 4直到ID==19遞減計數器應當執行從值15開始直到計數器是0。另外要注意的是,如果在此範圍之間存在任何A== 1/-1,則應該忽略它。 b。我還需要執行retain_A列,其中保留價值A整個counter

以下是我的預期產出。

ID A  retain_A dec_cnt 
    1 0   NA   NA 
    2 0   NA   NA 
    3 0   NA   NA 
    4 1   1   15 
    5 1   1   14 
    6 0   1   13 
    7 0   1   12 
    8 0   1   11 
    9 0   1   10 
10 0   1   9 
11 0   1   8 
12 0   1   7 
13 0   1   6 
14 0   1   5 
15 0   1   4 
16 -1   1   3 
17 1   1   2 
18 0   1   1 
19 1   1   0   
20 0   NA   NA 
21 -1   -1   15 
22 0   -1   14 
23 0   -1   13 
24 -1   -1   12 
25 0   -1   11 
26 0   -1   10 
27 0   -1   9 
28 0   -1   8 
29 0   -1   7 
30 0   -1   6 
31 0   -1   5 
32 0   -1   4 
33 0   -1   3 
34 0   -1   2 

類似的各種問題已張貼前兩天在解決方案使用for loop,另外,loop失敗如果數據點都超過35執行。我想避免for loop,因爲如果我們處理大量的數據,它的執行時間會更長。

的數據幀從張貼here

下面

問題採取的是,我使用以上引用的交試過的腳本。

dec_cnt <- 0 
    Retain_A <- NA 
    for (i in seq_along(df$A)) { 
    if (dec_cnt == 0) { 
     if (df$A[i] == 0) next 
    dec_cnt <- 15 
    Retain_A <- df$A[i] 
    df$Retain_A[i] <- df$A[i] 
    df$dec_cnt[i] <- dec_cnt 
    } else { 
    dec_cnt <- dec_cnt - 1 
    df$Retain_A[i] <- Retain_A 
    df$dec_cnt[i] <- dec_cnt 
    } 
} 
+0

爲什麼不找到所有第一個'1'和'-1',子集16行後面並添加一個序列(和'1' /'-1')?你能否以易於粘貼的形式提供你的例子,比如'dput()'? –

回答

2

我不認爲避免任何形式的循環,for或其他形式是不現實的。也許更現實的目標是避免遍歷每一個單值的循環,而不管它是否相關。

從2列輸入開始,讓我們預先設定的空列:

dat$retain_A <- NA 
dat$dec_cnt <- NA 

這裏我們可以得到一些效率:不是反覆進行比較,我們可以知道如果它匹配 - 1/1現在:

ind <- which(dat$A %in% c(-1,1)) 
last_match <- 0 
ind 
# [1] 4 5 16 17 19 21 24 

關鍵是要跟蹤last_match和丟棄它,並在接下來的15項之間的任何指標。

ind <- ind[ind > last_match] 
while (length(ind) > 0) { 
    i <- seq(ind[1], min(ind[1] + 15, nrow(dat))) 
    dat$dec_cnt[i] <- head(15:0, n = length(i)) 
    dat$retain_A[i] <- dat$A[ ind[1] ] 
    last_match <- ind[1] + 15 
    ind <- ind[ind > last_match] 
} 
dat 
# ID A retain_A dec_cnt 
# 1 1 0  NA  NA 
# 2 2 0  NA  NA 
# 3 3 0  NA  NA 
# 4 4 1  1  15 
# 5 5 1  1  14 
# 6 6 0  1  13 
# 7 7 0  1  12 
# 8 8 0  1  11 
# 9 9 0  1  10 
# 10 10 0  1  9 
# 11 11 0  1  8 
# 12 12 0  1  7 
# 13 13 0  1  6 
# 14 14 0  1  5 
# 15 15 0  1  4 
# 16 16 -1  1  3 
# 17 17 1  1  2 
# 18 18 0  1  1 
# 19 19 1  1  0 
# 20 20 0  NA  NA 
# 21 21 -1  -1  15 
# 22 22 0  -1  14 
# 23 23 0  -1  13 
# 24 24 -1  -1  12 
# 25 25 0  -1  11 
# 26 26 0  -1  10 
# 27 27 0  -1  9 
# 28 28 0  -1  8 
# 29 29 0  -1  7 
# 30 30 0  -1  6 
# 31 31 0  -1  5 
# 32 32 0  -1  4 
# 33 33 0  -1  3 
# 34 34 0  -1  2 

你會發現你的初始循環每行迭代一次,而這個解決方案每個非零隻迭代一次。

+0

@Yeah它工作!並且非常感謝解釋。 :) – Tareva

+0

@ r2evans,你也可以使用'rev(0:15)'而不是'head(15:0,n = length(i))' – parth

+0

不,不完全。你可以用'rev(0:15)'代替'15:0',但是你錯過了使用'head'的意圖。 – r2evans