如何根据分组列的最小唯一长度创建ID?

时间:2017-03-09 20:13:37

标签: r data.table

我有data.table与此类似:

set.seed(175232)
DT <- data.table( AU2 = sample(LETTERS[1:3], 10, T), INST= sample(LETTERS[1-5], 10), 
                  ZIP = replicate(10, paste0(sample(LETTERS[1:2],1), sample(10:15,1), collapse="")),
                  CU =  replicate(10, paste0(sample(LETTERS[1:3], 2), collapse = "" )))
DT[,AID1:= .GRP, by= AU2]
setkey(DT, AID1)
setorder(DT, AID1)

   AU2 INST ZIP CU AID1
 1:   B    A B11 BC    1
 2:   B    T B12 AC    1
 3:   B    S A13 AC    1
 4:   B    C A12 BC    1
 5:   B    Q B11 BC    1
 6:   B    J B12 BC    1
 7:   B    L A12 AC    1
 8:   C    I A11 BC    2
 9:   A    W A14 CB    3
10:   A    O B12 AB    3

我想基于3列中的唯一元素的长度创建ID,按另一列AID1分组。请注意,在这种情况下,AID1列显然是多余的,因为可以按AU2分组,但我使用AID1后者。首先,我输出每列中的最小唯一长度。

sd.cols = c("INST", "ZIP", "CU" )
DT[,  lapply(.SD, function(x){length(unique(x)) })  , by=AID1, .SDcols = sd.cols]

   AID1 INST ZIP CU
1:    1    7   4  2
2:    2    1   1  1
3:    3    2   2  2

然后到最小列,我可以运行

DT[,  which.min(lapply(.SD, function(x){length(unique(x)) }))  , by=AID1, .SDcols = sd.cols]

   AID1 V1
1:    1  3
2:    2  1
3:    3  1

也就是说,对于AID1 1,最小唯一长度在第3列,2为1,而3为1.现在,以AID1 2为例,最小长度在第1列中,其值在上一个表中的值为1,即没有重复,返回其原始ID 2。对于ID 1,最小值在第3列,其长度为2,我希望它返回AID1,加上相应的1:2,相应于第2列中的值。到目前为止,方法是编写一个小函数,并在data.table中通过引用运行它。

mk_id <- function(aid1, inst, zip, cu) {
  grp <- list(inst, zip, cu)
  u_grp <- lapply(grp,  function(x) {
    length(unique(x))
  })
  if (any(u_grp == 1)) {
    paste0(aid1)
  } else{
    paste0(aid1, "-", as.integer(factor(grp[[which.min(u_grp)]])) )
  }
}
DT[, ID:= mk_id(AID1, INST, ZIP, CU), by = AID1 ]
DT
    AU2 INST ZIP CU AID1  ID
 1:   B    A B11 BC    1 1-2
 2:   B    T B12 AC    1 1-1
 3:   B    S A13 AC    1 1-1
 4:   B    C A12 BC    1 1-2
 5:   B    Q B11 BC    1 1-2
 6:   B    J B12 BC    1 1-2
 7:   B    L A12 AC    1 1-1
 8:   C    I A11 BC    2   2
 9:   A    W A14 CB    3 3-2
10:   A    O B12 AB    3 3-1

虽然它有效,但我在写这个问题时想通了,但是,肯定有一种更直接的方式。

0 个答案:

没有答案