首页 > 解决方案 > data.table:基于其他列中存在值的新布尔列

问题描述

假设我有一个data.table带有数值的列,并且我想要一个新列,即TRUE某个数值是否存在于特定的其他列中,FALSE如果不存在。所以如果我有这张桌子:

    a   b   c
1   23  12  34
2   12  56  43
3   11  12  14
4   13  23  6
5   13  15  4
6   12  23  56
7   76  23  1
8   2   9   22
9   5   21  12
10  12  65  31

我想要一列告诉我列中有哪些行12ac即结果将是

    a   b   c   ac_12
1   23  12  34  FALSE
2   12  56  43  TRUE
3   11  12  14  FALSE
4   13  23  6   FALSE
5   13  15  4   FALSE
6   12  23  56  TRUE
7   76  23  1   FALSE
8   2   9   22  FALSE
9   5   21  12  TRUE
10  12  65  31  TRUE

我试过做类似的事情

val <- 12
cols <- c("a", "c")
dt[, ac_12 := lapply(.SD, function(x) val %in% x), .SDcols = cols]

但这没有用。我究竟做错了什么?

标签: rdata.table

解决方案


dat[, ac_12 := rowSums(do.call(cbind, lapply(.SD, `%in%`, val))) > 0, .SDcols = cols ]
#      a  b  c ac_12
#  1: 23 12 34 FALSE
#  2: 12 56 43  TRUE
#  3: 11 12 14 FALSE
#  4: 13 23  6 FALSE
#  5: 13 15  4 FALSE
#  6: 12 23 56  TRUE
#  7: 76 23  1 FALSE
#  8:  2  9 22 FALSE
#  9:  5 21 12  TRUE
# 10: 12 65 31  TRUE

为了看看发生了什么,让我们从最里面开始(硬编码参数只是为了这个演练):

lapply(dat[,c('a','c')], `%in%`, val)
# $a
#  [1] FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE
# $c
#  [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE

do.call(cbind, lapply(dat[,c('a','c')], `%in%`, val))
#           a     c
#  [1,] FALSE FALSE
#  [2,]  TRUE FALSE
#  [3,] FALSE FALSE
#  [4,] FALSE FALSE
#  [5,] FALSE FALSE
#  [6,]  TRUE FALSE
#  [7,] FALSE FALSE
#  [8,] FALSE FALSE
#  [9,] FALSE  TRUE
# [10,]  TRUE FALSE

rowSums(do.call(cbind, lapply(dat[,c('a','c')], `%in%`, val)))
#  [1] 0 1 0 0 0 1 0 0 1 1

推荐阅读