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

R 按因子和时间间隔计算发生次数,r,count,group-by,R,Count,Group By,我目前有一个单一的数据框(数据,nrow=10248),其中包含2013年7月1日至2013年10月3日期间标记的动物信息,包括日期(日期)、识别标签(id)、标记和释放动物的指定组(trip),以及是否检测到它们(存在;0=否,1=是)。请参见下面的示例: > data date id trip presence 26 2013-07-01 9360 1 1 27 2013-07-01 9361 1 1 28

我目前有一个单一的数据框(数据,nrow=10248),其中包含2013年7月1日至2013年10月3日期间标记的动物信息,包括日期(日期)、识别标签(id)、标记和释放动物的指定组(trip),以及是否检测到它们(存在;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年3月10日
  • “第二次旅行”中的所有动物都贴上了标签 2013年7月6日,允许漫游至2013年10月3日
  • 所有“旅行”组的开始日期不同,但最终于2013年3月10日结束
我的总体目标是通过因子“trip”计算在指定时间间隔(例如5天)内检测到多少动物(存在的唯一id=1)

我期望的输出如下(频率值与上表示例无关):

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


是否有人有任何建议,例如使用
xts
zoo
软件包或为每次“旅行”创建单独的数据帧?如果您需要更多信息,请告诉我

这也许是你的一个开始。不过,可能有更优雅的方式来实现这一点。我在回答中使用包
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)
请注意,在此解决方案中,我假设每次行程的开始日期是任何
行程
组中出现的第一个日期(不考虑presenece是1还是0,但如果需要,可以轻松调整)

还请注意,对于每个
跳闸
组,仅显示这些时间间隔,其中发生频率>=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)
来检查这一点。

使用聚合,使用
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
这并不是我们想要的,因为第三次旅行的开始日期应该是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

(谢谢你的推荐!我对
dplyr
的实验还不够,但它似乎很简单。你能进一步解释一下
突变(间隔=下限((as.numeric(date-min(date))/intrvl)+1)这一行中发生了什么吗%.%
?@ccapizzano我已经为这一行添加了一个解释。非常好,我能够配置一些代码,以输出每个间隔的唯一发射机数量。感谢您的帮助!这个解决方案很好,因为它非常紧凑。我只想知道为什么行程3的日期是2013-07-06。正如我理解的OP,时间间隔(例如5天)与每组的“开始日期”无关。好的捕获,@初学者。这可以通过将
trip
的每个值作为一个单独的数据框来实现。更新+1(仍然是一个非常紧凑的解决方案)感谢您提供使用
base
code的替代解决方案,非常感谢。我将很快试用!
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
(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