我有一个数据框,每个ID有24小时,如下所示:
library(data.table)
DT=data.table(id=c(rep(1,24),rep(2,24),rep(3,24)),
hour=c(rep(0:23,3)),
val=c(rep(c(18,36,27,18,36,39,99,99,72,81,54,72,18,9,36,27,18,90,36,27,18,45,54,63),3)))
然后我还有一个数据表,其中包含每个id的紧急开始和结束时间,如下所示:
c=data.table(id=c(1,2,3),start=c(3,6,9),end=c(9,12,4))
我必须在数据表a中追加一个列作为急速,然后标记它在每个id的高峰时间范围内的标记。就像id 1一样,高峰时间是3到9(3, 4,5,6,7,8,9)所以在DT中这些行的所有记录都应标记为列rush = 1和休息记录,其中rush = 0表示休息。
我试过这个
setkey(c, start, end)
DT[,hour_replica:=hour]
result <- foverlaps(DT, c, by.x=c('hour','hour_replica'),
by.y=c('start', 'end'))
但它会抛出错误
列start中的所有条目应为&lt; = data.table中列末尾的相应条目
感谢任何帮助。
答案 0 :(得分:2)
使用tidyverse
- 我还没有使用过data.table包,所以我选择了我认识的东西。您可能需要将data.table
格式切换为data.frame
或data_frame
- 这两种格式都有效,我只是不了解data.table
格式。
我还更改了您的急速数据的名称 - 使用名称c
是一个非常糟糕的主意 - 它可能会对c
函数进行大量标准调用!
DT=data_frame(
id=c(rep(1,24),rep(2,24),rep(3,24)),
hour=c(rep(0:23,3)), val=c(rep(c(18,36,27,18,36,39,99,99,72,81,54,72,18,9,36,27,18,90,36,27,18,45,54,63),3)))
rush=data_frame(id=c(1,2,3),start=c(3,6,9),end=c(9,12,4))
library(dplyr)
DT %>% left_join(rush) %>%
mutate(rush = hour >= start & hour <= end) %>%
select(-(start:end))
答案 1 :(得分:2)
一种简单的方法可能是:
DT[c, rush := as.numeric(start <= hour & end >= hour), on="id"]
DT
# id hour val rush
# 1: 1 0 18 0
# 2: 1 1 36 0
# 3: 1 2 27 0
# 4: 1 3 18 1
# 5: 1 4 36 1
# 6: 1 5 39 1
# 7: 1 6 99 1
#.......so on
答案 2 :(得分:1)
使用data.table
library(data.table)
DT=data.table(id=c(rep(1,24),rep(2,24),rep(3,24)),
hour=c(rep(0:23,3)),
val=c(rep(c(18,36,27,18,36,39,99,99,72,81,54,72,18,9,36,27,18,90,36,27,18,45,54,63),3)))
c=data.table(id=c(1,2,3),start=c(3,6,9),end=c(9,12,4))
# join condition & create rush = 1 where they match
DT[c, on = .(id, hour >= start, hour <= end), c("rush") := 1]
# replace NA (no match) with 0
DT[is.na(rush), rush := 0]
DT
#> id hour val rush
#> 1: 1 0 18 0
#> 2: 1 1 36 0
#> 3: 1 2 27 0
#> 4: 1 3 18 1
#> 5: 1 4 36 1
#> 6: 1 5 39 1
#> 7: 1 6 99 1
#> 8: 1 7 99 1
#> 9: 1 8 72 1
#> 10: 1 9 81 1
#> 11: 1 10 54 0
#> 12: 1 11 72 0
#> 13: 1 12 18 0
#> 14: 1 13 9 0
#> 15: 1 14 36 0
#> 16: 1 15 27 0
#> 17: 1 16 18 0
#> 18: 1 17 90 0
#> 19: 1 18 36 0
#> 20: 1 19 27 0
#> 21: 1 20 18 0
#> 22: 1 21 45 0
#> 23: 1 22 54 0
#> 24: 1 23 63 0
#> 25: 2 0 18 0
#> 26: 2 1 36 0
#> 27: 2 2 27 0
#> 28: 2 3 18 0
#> 29: 2 4 36 0
#> 30: 2 5 39 0
#> 31: 2 6 99 1
#> 32: 2 7 99 1
#> 33: 2 8 72 1
#> 34: 2 9 81 1
#> 35: 2 10 54 1
#> 36: 2 11 72 1
#> 37: 2 12 18 1
#> 38: 2 13 9 0
#> 39: 2 14 36 0
#> 40: 2 15 27 0
#> 41: 2 16 18 0
#> 42: 2 17 90 0
#> 43: 2 18 36 0
#> 44: 2 19 27 0
#> 45: 2 20 18 0
#> 46: 2 21 45 0
#> 47: 2 22 54 0
#> 48: 2 23 63 0
#> 49: 3 0 18 0
#> 50: 3 1 36 0
#> 51: 3 2 27 0
#> 52: 3 3 18 0
#> 53: 3 4 36 0
#> 54: 3 5 39 0
#> 55: 3 6 99 0
#> 56: 3 7 99 0
#> 57: 3 8 72 0
#> 58: 3 9 81 0
#> 59: 3 10 54 0
#> 60: 3 11 72 0
#> 61: 3 12 18 0
#> 62: 3 13 9 0
#> 63: 3 14 36 0
#> 64: 3 15 27 0
#> 65: 3 16 18 0
#> 66: 3 17 90 0
#> 67: 3 18 36 0
#> 68: 3 19 27 0
#> 69: 3 20 18 0
#> 70: 3 21 45 0
#> 71: 3 22 54 0
#> 72: 3 23 63 0
#> id hour val rush
由reprex package(v0.2.0)创建于2018-04-01。
答案 3 :(得分:1)
c[DT, on = 'id'][, .(rush = as.numeric((hour >= start &
hour <= end))), by = .(id, hour, val)]
一个班轮
使用c,在ID上右键加入DT,
然后执行rush = 1/0取决于小时/开始/结束,
by [id],[hour]和[val]所以包括这3列)
但我有一个问题,
对于组ID 3,从9开始到4结束,这将导致规则下的0冲 (小时&gt; =开始&amp;小时&lt; =结束)。
我猜你想要c(9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,0,1,2,3,4)全部算作&#34;赶紧&#34;。
与小时不同&gt; = start&amp;小时&lt; =结束,
如果id = 3
是小时&gt; =开始|小时&lt; =结束
所以,如果那是你想要的,添加一个if-else子句就可以解决它
c[DT, on = 'id'][, .(rush =
if (start < end) {
as.numeric((hour >= start & hour <= end))
} else{
as.numeric((hour >= start | hour <= end))
}), by = .(id, hour, val)]
希望这会有所帮助