【问题标题】:How to join and tag depending on condition如何根据条件加入和标记
【发布时间】:2018-04-02 06:18:47
【问题描述】:

我有一个数据框,每个 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 中附加一列作为 rush,然后标记它是否落在每个 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'))

但是会报错

列开头的所有条目都应该是

感谢任何帮助。

【问题讨论】:

  • 我一直很欣赏包含重现问题的代码的问题。谢谢。

标签: r datatable dplyr


【解决方案1】:

一个简单的方法可能是:

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】:

    使用tidyverse - 我没有使用 data.table 包,所以我使用了我知道的东西。您可能需要将 data.table 格式切换为 data.framedata_frame - 两者都可以,我只是不知道 data.table 格式。

    我还更改了您的 rush 数据的名称 - 使用名称 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))
    

    【讨论】:

      【解决方案3】:

      使用来自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 年 4 月 1 日创建。

      【讨论】:

        【解决方案4】:
        c[DT, on = 'id'][, .(rush = as.numeric((hour >= start &
                                                  hour <= end))), by = .(id, hour, val)]
        

        一个班轮

        使用c,在id上右加入DT,

        然后执行 rush=1/0 取决于小时/开始/结束,

        按 [id]、[hour] 和 [val] 所以包括这 3 列)

        但我有一个问题,

        对于组 id 3,从 9 开始到 4 结束,这将导致 0 rush under rule (小时>=开始和小时

        我猜你想要 c(9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,0,1,2,3,4) 所有算作“匆忙”。

        与小时不同>=start & hour

        如果 id=3

        现在是小时 >=开始 |小时

        所以如果这是你想要的,添加一个 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)]
        

        希望对你有帮助

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-11-13
          • 1970-01-01
          • 1970-01-01
          • 2022-11-12
          • 1970-01-01
          • 2021-09-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多