R data.table :(动态)前瞻性交叉联合

时间:2017-09-12 00:04:26

标签: r data.table cross-join

我想知道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

在这里,我总共有8个观察4个不同的项目(ID 18,46,74和165)。每个项目记录在几个类别(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)],表现得像这样。我很感激任何帮助/提示。

3 个答案:

答案 0 :(得分:6)

我认为您可以通过非equi联接中的.EACHI执行此操作。然后,您可以使用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

答案 1 :(得分:5)

一种方式:

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 :(得分:2)

不是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