1

这实际上是我几周前在这里发布的另一个问题的后续,并得到了答案。

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

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)

这一切都适用于单个数据集,即一组的一个时间序列。然而,我现在正在苦苦挣扎的是如何根据分组变量(Soil)操作上述代码以对同一 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()首先根据土壤进行分组,这将起作用,但我找不到任何这样做的方法。

因此,请提供任何帮助!

4

2 回答 2

3

如果你使用这个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]
于 2014-05-13T14:35:38.513 回答
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))
于 2014-05-13T18:42:11.947 回答