我有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
虽然它有效,但我在写这个问题时想通了,但是,肯定有一种更直接的方式。