2014-05-13 38 views
1

这真的是从another question的后续几个星期前我发布在这里,并得到了答案。根据其他变量组使用rle()R

在我最初的问题中,我想查找数据集中径流事件之间的天数。如下面的数据样本中所示:

Date  Runoff No_Days 
01/01/1980 0  4 
02/01/1980 0  3 
03/01/1980 0  2 
04/01/1980 0  1 
05/01/1980 4.5  0 
06/01/1980 2  0 
07/01/1980 0  6 
08/01/1980 0  5 
09/01/1980 0  4 
10/01/1980 0  3 
11/01/1980 0  2 
12/01/1980 0  1 
13/01/1980 1.2  0 
14/01/1980 0  4  
15/01/1980 0  3 
16/01/1980 0  2 
17/01/1980 0  1 
18/01/1980 0.8  0 

我设法得到此使用以下代码:

DF$No_Days <-unlist(lapply(rle(DF$Runoff>0.05)$lengths,function(x) rev(seq(x:1)))) 
DF$No_Days <-ifelse(DF$Runoff>0.05,0,DF$No_Days) 

这一切都可以很好地用于单个数据集即,一个时间序列的一组。然而,我现在正在努力的是如何操作上面的代码,以根据分组变量(土壤)为相同的data.table中的许多时间序列数据集做同样的事情,例如:

Date  Runoff No_Days Soil 
01/01/1980 0  4  Clay 
02/01/1980 0  3  Clay  
03/01/1980 0  2  Clay  
04/01/1980 0  1  Clay  
05/01/1980 4.5  0  Clay 
06/01/1980 2  0  Clay 
07/01/1980 0  6  Clay 
08/01/1980 0  5  Clay 
09/01/1980 0  4  Clay 
10/01/1980 0  3  Clay 
11/01/1980 0  2  Clay 
12/01/1980 0  1  Clay 
13/01/1980 1.2  0  Clay 
14/01/1980 0  4  Clay 
15/01/1980 0  3  Clay 
16/01/1980 0  2  Clay 
17/01/1980 0  1  Clay 
18/01/1980 0.8  0  Clay 
01/01/1980 0  5  Sand 
02/01/1980 0  4  Sand 
03/01/1980 0  3  Sand 
04/01/1980 0  2  Sand 
05/01/1980 0  1  Sand 
06/01/1980 2  0  Sand 
07/01/1980 0  11  Sand 
08/01/1980 0  10  Sand 
09/01/1980 0  9  Sand 
10/01/1980 0  8  Sand 
11/01/1980 0  7  Sand 
12/01/1980 0  6  Sand 
13/01/1980 0  5  Sand 
14/01/1980 0  4  Sand  
15/01/1980 0  3  Sand 
16/01/1980 0  2  Sand 
17/01/1980 0  1  Sand 
18/01/1980 0.8  0  Sand 

目前,如果我运行代码,它不会区分不同的土壤类型,因此在每个时间序列之后都不会重新启动测序。

从阅读中可以看出,我可能需要将原始代码中的lapply()更换为by()。我认为只要rle()首先根据土壤进行分组,但我无法找到任何方法。

所以任何帮助表示赞赏!

回答

2

如果使用data.table包,这是很容易的:

install.packages("data.table") 
library(data.table) 
DF = data.table(DF) 

DF[,No_Days:=unlist(lapply(rle(Runoff>0.05)$lengths,function(x) rev(seq(x:1)))),by=Soil] 
DF[Runoff <= 0.05, No_Days:=0] 
+1

分组一种享受。我不知道我是如何没有发现这一点的,因为我一直在用data.table处理其他东西。谢谢! –

1

如果你有兴趣在基础R这样做,以及,你可以使用ave来得到相同的结果。为方便起见,我将定义

countdown <- function(events) { 
    unlist(with(rle(events), 
     Map(function(v,l) { 
      if(v) rep.int(0,l) 
      else l:1} 
     , values, lengths) 
    )) 
} 

然后,你会发现没有土壤类型的答案与

DF <- transform(DF, No_Days=countdown(Runoff>0.05)) 

,然后做通过这一工程的土壤类型,你能满足

DF <- transform(DF, No_Days=ave(Runoff>0.05, Soil, FUN=countdown))