按因子和时间间隔计算发生次数

时间:2014-05-27 12:34:20

标签: r count group-by

我目前有一个数据框(数据,nrow = 10248),标记的动物信息从2013年7月1日到2013年10月3日,包括日期(日期),识别标签(id),指定的组动物被标记和释放(旅行),如果它们被检测到(存在; 0 =否,1 =是)。请参阅下面的示例:

> data
            date   id trip presence
26    2013-07-01 9360    1        1
27    2013-07-01 9361    1        1
28    2013-07-02 9362    1        0
29    2013-07-02 9363    1        0
30    2013-07-03 9364    1        1
2349  2013-07-03 9343    1        1
2350  2013-07-04 9344    1        0
2351  2013-07-04 9345    1        1
2352  2013-07-05 9346    1        1
2353  2013-07-05 9347    1        1
2354  2013-07-06 9360    1        1
7102  2013-07-06 9416    2        1
7103  2013-07-06 9417    2        1
7104  2013-07-07 9360    1        1
7105  2013-07-07 9419    2        1
7106  2013-07-07 9420    2        1
7107  2013-07-08 9360    1        1
11102 2013-07-08 9386    3        0
11103 2013-07-08 9387    3        0
11104 2013-07-09 9360    1        1
11105 2013-07-09 9343    1        1
11106 2013-07-09 9390    3        1
11107 2013-07-09 9391    3        1

另一个重要的信息是每个"旅行"组有不同的开始日期。例如:

  • 所有动物在2013年7月1日被标记为"旅行1"被允许漫游 自由到2013年10月3日。
  • 所有动物在"旅行2"被标记了 2013年7月6日,并允许漫游至2013年10月3日。
  • 所有"旅行"团体有不同的开始日期,但最终将于2013年10月3日结束。

我的总体目标是通过因子"旅行"计算在指定的时间间隔(例如5天)内检测到多少动物(具有存在= 1的唯一身份)。

我想要的输出类似于以下内容(频率值与上表示例无关):

trip         interval   frequency
   1    07/01 - 07/05          5
   1    07/06 - 07/10          4
   1    07/11 - 07/15          4
   2    07/06 - 07/10          5
   2    07/11 - 07/15          4
   2    07/16 - 07/20          3
   3    07/08 - 07/12          6
   3    07/13 - 07/17          6
   3    07/18 - 07/22          5

*注意旅行的不同开始日期。

是否有人会提出任何建议,例如使用xtszoo个包或为每个"旅行创建单独的数据框?如果您需要更多信息,请与我们联系!

2 个答案:

答案 0 :(得分:4)

这可能是你的开始。但是,可能有更优雅的方式。我在我的回答中使用了包dplyr,并假设您的data.frame被称为dd

dd$date <- as.Date(dd$date, format="%Y-%m-%d")

intrvl <- 5

require(dplyr)

result <- dd %.%
  group_by(trip) %.%
  mutate(interval = floor((as.numeric(date - min(date)))/intrvl)+1) %.%
  filter(presence == 1) %.%
  group_by(interval, add = TRUE) %.%
  summarize(startDate = min(date),
            endDate = as.Date(startDate + intrvl -1, origin = "1970-01-01"),
            frequency = n()) %.%
  select(-interval)

根据您的示例数据,结果将是:

> result
#  trip  startDate    endDate frequency
#1    1 2013-07-01 2013-07-05         7
#2    1 2013-07-06 2013-07-10         5
#3    2 2013-07-06 2013-07-10         4
#4    3 2013-07-09 2013-07-13         2

请注意,在此解决方案中,我假设每次旅行的开始日期是任何trip组中出现的第一个日期(不考虑presenece为1或0,但可以轻松调整如果需要)。

另请注意,每个trip组仅显示那些时间间隔,其中出现的频率> = 1。

最后但并非最不重要的是,您可以通过将变量intrvl更改为任何其他数字来轻松更改时间间隔。

OP评论后编辑:

以下一行

mutate(interval = floor((as.numeric(date - min(date)))/intrvl)+1) %.%

首先创建一个新列interval,然后计算每个trip组的最小日期之间的差异(例如,第一组的2013-07-01)和当前行中的日期条目,这将转换为数字。例如,如果差值为3,则将3除以intrvl(5),这使得3/5在0和1之间。然后,floor函数将此数字向下舍入到下一个更小的整数当前值,因此它为0.最后,您添加1,这是该行的间隔组(第一个间隔组在您的示例中从2013-07-01运行到2013-07-05)。您可以通过从代码中删除最后一个%.% select(-interval)来检查这一点。

答案 1 :(得分:4)

使用聚合,使用cut.Date创建存储桶:

aggregate(presence ~ trip + cut(as.Date(date), breaks='5 day'), data=data, FUN=sum)
##   trip cut(as.Date(date), breaks = "5 day") presence
## 1    1                           2013-07-01        7
## 2    1                           2013-07-06        5
## 3    2                           2013-07-06        4
## 4    3                           2013-07-06        2

这不是想要的,因为旅行3的开始日期应该是2013-07-08。按trip拆分数据框,执行相同的计算(但无需在trip上聚合)并重新组合:

(d <- do.call(rbind,
    by(data, data$trip, 
       FUN=function(x) aggregate(presence ~ cut(as.Date(date), breaks='5 day'),
                                 data=x, FUN=sum)
    )
))
##     cut(as.Date(date), breaks = "5 day") presence
## 1.1                           2013-07-01        7
## 1.2                           2013-07-06        5
## 2                             2013-07-06        4
## 3                             2013-07-08        2

这里的行名称表示行程:

d$trip <- gsub('[.].*$', '', rownames(d))
d
##     cut(as.Date(date), breaks = "5 day") presence trip
## 1.1                           2013-07-01        7    1
## 1.2                           2013-07-06        5    1
## 2                             2013-07-06        4    2
## 3                             2013-07-08        2    3