代码之家  ›  专栏  ›  技术社区  ›  Ricky

如何根据条件加入和标记

  •  2
  • Ricky  · 技术社区  · 8 年前

    我有一个数据框,每个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,rest记录的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'))
    

    但它抛出了一个错误

    “开始”列中的所有条目都应为<=数据列中的相应条目结束。桌子

    非常感谢您的帮助。

    4 回复  |  直到 8 年前
        1
  •  2
  •   MKR    8 年前

    一种简单的方法可以是:

    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
  •  2
  •   Melissa Key    8 年前

    使用 tidyverse -我没有使用这些数据。桌上的包裹,所以我带着我知道的东西去了。您可能需要切换 data.table 格式设置为 data.frame data_frame -两个都可以,我只是不知道 数据桌子 总体安排

    我还更改了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
  •  1
  •   Tung    8 年前

    使用来自的非等联接 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
    

    创建日期:2018年4月1日 reprex package (v0.2.0)。

        4
  •  1
  •   SunLisa    8 年前
    c[DT, on = 'id'][, .(rush = as.numeric((hour >= start &
                                              hour <= end))), by = .(id, hour, val)]
    

    一个衬里

    使用c,右键连接id上的DT,

    然后,根据小时/开始/结束,进行高峰=1/0,

    按[id]、[小时]和[瓦尔]计算,因此包括这3列)

    但我有个问题,

    对于id为3的组,从9开始,到4结束,根据规则将导致0次冲刺 (小时>=开始&小时<=结束)。

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

    与小时不同>=启动(&A);小时(<)=终止

    如果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)]
    

    希望这有帮助

    推荐文章