在R中查找连续两周的第一个日期(数据表)
我试图找到第一个日期(每组),其中一周和下一周都有记录。周不从周一开始,但定义为七天 假设某个日期是第一周的第一天,我将尝试测试第二个“周”中的日期记录数是否大于1在R中查找连续两周的第一个日期(数据表),r,date,indexing,data.table,R,Date,Indexing,Data.table,我试图找到第一个日期(每组),其中一周和下一周都有记录。周不从周一开始,但定义为七天 假设某个日期是第一周的第一天,我将尝试测试第二个“周”中的日期记录数是否大于1 library(data.table) dt=data.table(date=c(1,9,10,15,18,3,4,7,7,19,21,27), group=c(rep("a", 5), rep("b",7))) > dt date group 1: 1 a 2:
library(data.table)
dt=data.table(date=c(1,9,10,15,18,3,4,7,7,19,21,27),
group=c(rep("a", 5), rep("b",7)))
> dt
date group
1: 1 a
2: 9 a
3: 10 a
4: 15 a
5: 18 a
6: 3 b
7: 4 b
8: 7 b
9: 7 b
10: 19 b
11: 21 b
12: 27 b
适用于data.frame的for循环如下所示:
df <- data.frame(dt)
for(i in 1:length(df$date)){
df$count[i] <- sum(df$date >= df$date[i] + 7 &
df$date < df$date[i] + 14 &
df$group == df$group[i])
}
> df
date group count
1 1 a 2
2 9 a 1
3 10 a 1
4 15 a 0
5 18 a 0
6 3 b 0
7 4 b 0
8 7 b 1
9 7 b 1
10 19 b 1
11 21 b 0
12 27 b 0
dt[, date/sum(date), by=group]
问题是,我不明白如何创建一个对data.table有效的索引函数。非常感谢您的帮助。为什么不使用您创建的循环
dt[,count:=date]
for(i in 1:length(dt$date)){
set(dt,i,3L, sum(dt$date >= dt$date[i] + 7 &
dt$date < dt$date[i] + 14 &
dt$group == dt$group[i]))
}
dt
# date group count
# 1: 1 a 2
# 2: 9 a 1
# 3: 10 a 1
# 4: 15 a 0
# 5: 18 a 0
# 6: 3 b 0
# 7: 4 b 0
# 8: 7 b 1
# 9: 7 b 1
#10: 19 b 1
#11: 21 b 0
#12: 27 b 0
dt[,count:=日期]
对于(1中的i:长度(dt$日期)){
集合(dt,i,3L,总和)(dt$date>=dt$date[i]+7&
dt$日期
by
的工作方式类似于tapply
。您通过列(例如组)中的变量将data.table
拆分为mini data.tables,在整个mini data.table上执行一个函数,为每个mini data.table返回一些内容,然后组合返回的内容以生成输出。我认为这是可行的:
# set the key for the rolling merges
setkey(dt, group, date)
# find start and end point of the intervals you want
start = dt[J(group, date + 7 ), .I, roll = -Inf, by = .EACHI]$I
end = dt[J(group, date + 13), .I, roll = Inf, by = .EACHI]$I
# if start is 0, the first condition is not satisfied, so set count to 0
dt[, count := (start != 0) * (end - start + 1)]
dt
# date group count
# 1: 1 a 2
# 2: 9 a 1
# 3: 10 a 1
# 4: 15 a 0
# 5: 18 a 0
# 6: 3 b 0
# 7: 4 b 0
# 8: 7 b 1
# 9: 7 b 1
#10: 19 b 1
#11: 21 b 0
#12: 27 b 0
不幸的是@eddi建议的解决方案不再适用于
R 3.1.2
和数据。表1.9.4
。由于此错误而失败:
Error in dt[J(group, date + 13), .I, roll = Inf]$.I :
$ operator is invalid for atomic vectors
下面的代码可以工作,但使用新的foverlaps
功能是一个快速而肮脏的解决方法。我确信一定有办法解决滚动联接问题
# Find start and end point of the intervals you want
dt[, start := date + 7]
dt[, end := date + 13]
# Make two data tables for overlapping dates.
dt2 <- dt[, c("group", "start", "end")]
dt[, date2 := date] # copy date (foverlaps need an interval).
# Sort by date and overlap-merge with week ranges.
setkey(dt, group, date, date2)
dt3 <- foverlaps(dt2, dt, by.x=c("group", "start", "end"))
# Count unique values to get number of records in following week.
setkey(dt, group, start, end)
setkey(dt3, group, i.start, i.end)
dt4 <- unique(dt)[dt3]
dt4[, count := ifelse(is.na(i.start), 0L, length(unique(i.start))), by=date]
# Cleaning up.
dt5 <- dt[unique(dt4)]
dt5 <- dt5[, c("date", "group", "count")]
# > dt5
# date group count
# 1: 1 a 2
# 2: 9 a 1
# 3: 10 a 1
# 4: 15 a 0
# 5: 18 a 0
# 6: 3 b 0
# 7: 4 b 0
# 8: 7 b 1
# 9: 7 b 1
#10: 19 b 1
#11: 21 b 0
#12: 27 b 0
#找到所需间隔的起点和终点
dt[,开始:=日期+7]
dt[,结束:=日期+13]
#为重叠的日期制作两个数据表。
dt2您能否解释更多关于dt[,date/sum(date),by=group]
?你期望什么样的产出?什么是计数?回收去年的代码,不幸的是,这个解决方案不再有效。它抛出一个错误:dt[J(组,日期+13),.I,roll=Inf]$中的错误。I:$运算符对原子向量无效
。我使用了一种(丑陋的)方法来解决foverlaps
的问题(参见下面的答案)。必须有一种方法来避免无效运算符错误,但仍然使用滚动联接?@BramVisser修复了-错误(主要)是由于1.9.4在没有明确说明的情况下生成的,这很快。谢谢我知道这很简单,似乎还记得在导入数据时,启动消息中提到了一些关于.EACHI的内容。table。。。我猜关注这些消息是件好事。只需删除该命令末尾的$.I
。它已经返回了一个向量。浏览v1.9.4 README.md文件中的新闻以了解更改。