2014-11-20 98 views
0

已經有如何計算零和一(或其他值)的連續串幾次討論。我已經玩過這些功能,但我無法輕易弄清楚如何讓它們適用於我的具體問題。計數連續串在使用功能,如<strong>RLE</strong>或<strong>cumsum</strong>多組

我正在按時間(「年」)和地點(「ID」)組織生態存在/缺勤數據(「pres.abs」= 1或0)。對於每個位置ID,我想分別計算連續的長度和零時間。如果這些不能計算,我想返回「NA」。

下面是數據看起來像(前3列)和我希望實現的輸出(最後2列)的示例。理想情況下,這是一個非常快速的函數,避免了for-loops,因爲真實的數據幀包含約15,000行。

year = rep(1:10, times=3) 
id = c(rep(1, times=10), rep(2, times=10), rep(3, times=10)) 
pres.abs.id.1 = c(0, 0, 0, 1, 1, 1, 0, 0, 1, 1) #Pres/abs data at site 1 across time 
pres.abs.id.2 = c(1, 1, 0, 1, 0, 0, 1, 0, 0, 0) #Pres/abs data at site 2 across time 
pres.abs.id.3 = c(0, 0, 0, 0, 0, 1, 1, 1, 1, 1) #Pres/abs data at site 3 across time 
pres.abs = c(pres.abs.id.1, pres.abs.id.2, pres.abs.id.3) 
dat = data.frame(id, year, pres.abs) 

dat$cumul.zeroes = c(1,2,3,NA,NA,NA,1,2,NA,NA,NA,NA,1,NA,1,2,NA,1,2,3,1,2,3,4,5,NA,NA,NA,NA,NA) 
dat$cumul.ones = c(NA,NA,NA,1,2,3,NA,NA,1,2,1,2,NA,1,NA,NA,1,NA,NA,NA,NA,NA,NA,NA,NA,1,2,3,4,5) 

> dat 
    id year pres.abs cumul.zeroes cumul.ones 
1 1 1  0   1   NA 
2 1 2  0   2   NA 
3 1 3  0   3   NA 
4 1 4  1   NA   1 
5 1 5  1   NA   2 
6 1 6  1   NA   3 
7 1 7  0   1   NA 
8 1 8  0   2   NA 
9 1 9  1   NA   1 
10 1 10  1   NA   2 
11 2 1  1   NA   1 
12 2 2  1   NA   2 
13 2 3  0   1   NA 
14 2 4  1   NA   1 
15 2 5  0   1   NA 
16 2 6  0   2   NA 
17 2 7  1   NA   1 
18 2 8  0   1   NA 
19 2 9  0   2   NA 
20 2 10  0   3   NA 
21 3 1  0   1   NA 
22 3 2  0   2   NA 
23 3 3  0   3   NA 
24 3 4  0   4   NA 
25 3 5  0   5   NA 
26 3 6  1   NA   1 
27 3 7  1   NA   2 
28 3 8  1   NA   3 
29 3 9  1   NA   4 
30 3 10  1   NA   5 

非常感謝您的幫助。

回答

3

下面是使用rlesequence一個基礎R方式:

dat <- within(dat, { 
    cumul.counts <- unlist(lapply(split(pres.abs, id), function(x) sequence(rle(x)$lengths))) 
    cumul.zeroes <- replace(cumul.counts, pres.abs == 1, NA) 
    cumul.ones <- replace(cumul.counts, pres.abs == 0, NA) 
    rm(cumul.counts) 
}) 

# id year pres.abs cumul.ones cumul.zeroes 
# 1 1 1  0   NA   1 
# 2 1 2  0   NA   2 
# 3 1 3  0   NA   3 
# 4 1 4  1   1   NA 
# 5 1 5  1   2   NA 
# 6 1 6  1   3   NA 
# 7 1 7  0   NA   1 
# 8 1 8  0   NA   2 
# 9 1 9  1   1   NA 
# 10 1 10  1   2   NA 
# 11 2 1  1   1   NA 
# 12 2 2  1   2   NA 
# 13 2 3  0   NA   1 
# 14 2 4  1   1   NA 
# 15 2 5  0   NA   1 
# 16 2 6  0   NA   2 
# 17 2 7  1   1   NA 
# 18 2 8  0   NA   1 
# 19 2 9  0   NA   2 
# 20 2 10  0   NA   3 
# 21 3 1  0   NA   1 
# 22 3 2  0   NA   2 
# 23 3 3  0   NA   3 
# 24 3 4  0   NA   4 
# 25 3 5  0   NA   5 
# 26 3 6  1   1   NA 
# 27 3 7  1   2   NA 
# 28 3 8  1   3   NA 
# 29 3 9  1   4   NA 
# 30 3 10  1   5   NA 
+0

太好了!你是一個真正的wizaRd。非常感謝! – MCNC 2014-11-20 20:57:01

1

這裏有一個選項與dplyr:

require(dplyr) 
dat %>% 
    group_by(id, x = cumsum(c(0,diff(pres.abs)) != 0)) %>% 
    mutate(cumul.zeros = ifelse(pres.abs, NA_integer_, row_number()), 
     cumul.ones = ifelse(!pres.abs, NA_integer_, row_number())) %>% 
    ungroup() %>% select(-x) 

#Source: local data frame [30 x 5] 
# 
# id year pres.abs cumul.zeros cumul.ones 
#1 1 1  0   1   NA 
#2 1 2  0   2   NA 
#3 1 3  0   3   NA 
#4 1 4  1   NA   1 
#5 1 5  1   NA   2 
#6 1 6  1   NA   3 
#7 1 7  0   1   NA 
#8 1 8  0   2   NA 
#9 1 9  1   NA   1 
#10 1 10  1   NA   2 
#11 2 1  1   NA   1 
#12 2 2  1   NA   2 
#13 2 3  0   1   NA 
#14 2 4  1   NA   1 
#15 2 5  0   1   NA 
#16 2 6  0   2   NA 
#17 2 7  1   NA   1 
#18 2 8  0   1   NA 
#19 2 9  0   2   NA 
#20 2 10  0   3   NA 
#21 3 1  0   1   NA 
#22 3 2  0   2   NA 
#23 3 3  0   3   NA 
#24 3 4  0   4   NA 
#25 3 5  0   5   NA 
#26 3 6  1   NA   1 
#27 3 7  1   NA   2 
#28 3 8  1   NA   3 
#29 3 9  1   NA   4 
#30 3 10  1   NA   5