【问题标题】:R data.table: (dynamic) forward looking Cross-JoinsR data.table:(动态)前瞻性交叉连接
【发布时间】:2018-02-20 07:15:42
【问题描述】:

我想知道 data.table 中的 CJ() 方法是否有一个选项来获取由评估条件形成的向量,而不是运行完整的交叉连接。

数据

library(data.table)
df<-data.table(
  ID=c(18L,  18L,  18L,  46L,  74L,  74L, 165L, 165L), 
  cat=c(1300L, 1320L, 1325L, 1300L, 1300L, 1325L, 1300L, 1325L),
  low=c(24.625, 16.250, 14.500, 43.625, 58.250, 45.375, 90.750, 77.875),
  high=c(26.625, 17.500, 15.500, 45.625, 60.000, 47.375, 92.750, 79.875)
  )

df
    ID  cat    low   high
1:  18 1300 24.625 26.625
2:  18 1320 16.250 17.500
3:  18 1325 14.500 15.500
4:  46 1300 43.625 45.625
5:  74 1300 58.250 60.000
6:  74 1325 45.375 47.375
7: 165 1300 90.750 92.750
8: 165 1325 77.875 79.875

在这里,我对 4 个不同的项目(ID 18、46、74 和 165)总共有 8 个观察值。每个项目都记录在几个类别中(cat 1300、1320、1325)并进行两次测量(低和高)。

期望的输出

我现在想创建一个表,通过交叉连接为每个项目 (ID) 连接每个类别 (cat) 的低值与所有类别的高值较大。因此,我想要的输出看起来像

    ID  cat  cat_large    low   high
1:  18 1300      1320  24.625 17.500
2:  18 1300      1325  24.625 15.500
3:  18 1320      1325  16.250 15.500
4:  74 1300      1325  58.250 47.375
5: 165 1300      1325  90.750 79.875

我在其中添加了 cat_high 以指示在低/高中加入了哪两个类别。

不幸的是,我找不到正确的方法来修改我的完整交叉联接df[,CJ(low=low,high=high),by=.(ID)],使其表现得像这样。我很感激任何帮助/提示。

【问题讨论】:

    标签: r data.table cross-join


    【解决方案1】:

    一种方式:

    df[, c(
      CJ(cat = cat, lcat = cat, sorted = FALSE),
      CJ(low = low, high = high, sorted = FALSE)  
    ), by=ID][lcat > cat]
    
        ID  cat lcat    low   high
    1:  18 1300 1320 24.625 17.500
    2:  18 1300 1325 24.625 15.500
    3:  18 1320 1325 16.250 15.500
    4:  74 1300 1325 58.250 47.375
    5: 165 1300 1325 90.750 79.875
    

    【讨论】:

      【解决方案2】:

      我认为您可以通过 .EACHI 在非 equi 连接中执行此操作。然后,您可以使用 i. 前缀来选择从哪个表中获取输出变量:

      df[, c(.SD,.(larger_cat=cat))][
        df, on=.(ID==ID, cat > cat), .(larger_cat, low=i.low, high), by=.EACHI, nomatch=0
      ]
      
      #    ID  cat larger_cat    low   high
      #1:  18 1300       1320 24.625 17.500
      #2:  18 1300       1325 24.625 15.500
      #3:  18 1320       1325 16.250 15.500
      #4:  74 1300       1325 58.250 47.375
      #5: 165 1300       1325 90.750 79.875
      

      【讨论】:

      • 我觉得我应该能够做到:df[df, on=.(ID==ID, cat &gt; cat), .(larger_cat=x.cat,low=i.low, high), by=.EACHI, nomatch=0] 但这出于某种未知原因破坏了我的 lowhigh 输出
      • 回复您的评论,我不确定,但我确实注意到 i.* 和 x.* 向量的长度不同,比较 df[df, on=.(ID==ID, cat &gt; cat), length(i.low), by=.EACHI, nomatch=0]df[df, on=.(ID==ID, cat &gt; cat), length(high), by=.EACHI, nomatch=0] 如果这是唯一的问题,也许repfirst 会解决它..?
      • 感谢@thelatemail!这工作得非常快,我很可能最终会出于我的目的使用它。我已经勾选了弗兰克的答案(它完成了相同的任务,但为了我的目的需要更长的时间),尽管以防万一未来的读者正在寻找我的问题标题中指出的 CJ 解决方案。我很欣赏你的工作!
      【解决方案3】:

      不是dplyr 解决方案,但我认为以下是另一种选择。

      library(dplyr)
      library(tidyr)
      
      df2 <- df %>%
        group_by(ID) %>%
        complete(low, high) %>%
        mutate(cat_large = cat) %>%
        group_by(ID, low) %>%
        mutate(cat = na.omit(cat)) %>%
        group_by(ID, high) %>%
        mutate(cat_large = na.omit(cat_large)) %>%
        filter(low > high) %>%
        arrange(ID, desc(low), desc(high)) %>%
        select(ID, cat, cat_large, low, high)
      df2
      # A tibble: 5 x 5
      # Groups:   ID, high [4]
           ID   cat cat_large    low   high
        <int> <int>     <int>  <dbl>  <dbl>
      1    18  1300      1320 24.625 17.500
      2    18  1300      1325 24.625 15.500
      3    18  1320      1325 16.250 15.500
      4    74  1300      1325 58.250 47.375
      5   165  1300      1325 90.750 79.875
      

      【讨论】:

        猜你喜欢
        • 2014-03-28
        • 1970-01-01
        • 2013-08-03
        • 1970-01-01
        • 2011-07-20
        • 2012-08-15
        • 1970-01-01
        • 2012-11-09
        • 2019-08-14
        相关资源
        最近更新 更多