如何根据条件加入和标记

时间:2018-04-02 06:18:48

标签: r datatable dplyr

我有一个数据框,每个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中列末尾的相应条目

感谢任何帮助。

4 个答案:

答案 0 :(得分:2)

使用tidyverse - 我还没有使用过data.table包,所以我选择了我认识的东西。您可能需要将data.table格式切换为data.framedata_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)]

希望这会有所帮助