Powiedz, że mam data.table z wartościami numerycznymi i chcę nowej kolumny TRUE, jeśli pewna wartość numeryczna istnieje w określonych innych kolumnach, a FALSE Jeśli nie. Więc jeśli mam tę tabelę:

    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

I chcę kolumny, która mówi mi, które wiersze mają 12 w kolumnach a lub c, tj. Wynik byłby

    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

Próbowałem robić coś takiego

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

Ale to nie zadziałało. Co ja robię źle?

0
Wiktor Gustafsson 19 marzec 2020, 17:29

1 odpowiedź

Najlepsza odpowiedź
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

Aby zobaczyć, co się dzieje, zacznijmy od wewnętrznego (najbardziej kodujące argumenty tylko dla tego przejścia):

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
0
r2evans 22 marzec 2020, 23:46