我目前有一个数据框(数据,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
另一个重要的信息是每个"旅行"组有不同的开始日期。例如:
我的总体目标是通过因子"旅行"计算在指定的时间间隔(例如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
*注意旅行的不同开始日期。
是否有人会提出任何建议,例如使用xts
或zoo
个包或为每个"旅行创建单独的数据框?如果您需要更多信息,请与我们联系!
答案 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