Проверьте, появляется ли строка в каком-либо столбце (кроме 1-го) в data.table - PullRequest
1 голос
/ 31 марта 2019

Исходя из таблицы data.table, DT, с m строковыми столбцами, как можно помечать строки, в которых строка, скажем, «BlaBla» появляется хотя бы в одном столбце?

Что я хочу:

DT[, flag_BlaBLa:=(test if "BlaBLa" appears in any column except the first one)]

Я не хочу делать явную ссылку на имена столбцов.Скорее мне нужно сослаться на столбец 2 на максимальное число столбцов в DT (возможно: 2:ncol(DT)).Почему бы и нет?На самом деле, у меня есть список data.frames с различным количеством столбцов в каждом.Мне нужно создать флаг, как указано выше, для всех data.frames в списке

Edit1: добавление воспроизводимого примера.Edit2: изменение некоторых строк «BlaBLa» на «BlaBLa + что-то».Это также должно считаться совпадением, так как они включают «BlaBLa».

DT начинается с cols a,b,c, и я хочу, чтобы скрипт создал flag_BlaBLa.Конечный результат будет:

DT <- data.table(a=c("x","y","z",'w'),
                 b=c('BlaBLa','BLe','Bli','BlaBLaSometing'), 
                 c=c('Bla','BLe','BlaBLa','Blo'), 
                 flag_BlaBLa=c(T,F,T,T)
                 )

Для списка конечный результат должен быть:

DT1 <- data.table(a=c("x","y","z",'w'),
                 b=c('BlaBLa','BLe','Bli','BlaBLaSomething'), 
                 c=c('Bla','BLe','BlaBLa','Blo'), 
                 flag_BlaBLa=c(T,F,T,T)
                 )

DT2 <- data.table(a=c("q","j","p"),
                 b=c('BLe','Bli','BlaBLa'), 
                 flag_BlaBLa=c(F,F,T)
                 )
l <- list(DT1,DT2)

Ответы [ 4 ]

3 голосов
/ 31 марта 2019

Мы можем указать интересующие столбцы в .SDcols, пройтись по Подмножеству data.table (.SD), проверить, равно ли оно 'BlaBLa', Reduce это одному логическому vector, чтобы создать колонка

library(data.table)
lapply(l, function(x) x[, flag_BlaBLa := Reduce(`|`, lapply(.SD, `==`, 
           "BlaBLa")), .SDcols = 2:ncol(x)][])
#[[1]]
#   a      b      c flag_BlaBLa
#1: x BlaBLa    Bla        TRUE
#2: y    BLe    BLe       FALSE
#3: z    Bli BlaBLa        TRUE
#4: w BlaBLa    Blo        TRUE

#[[2]]
#   a      b flag_BlaBLa
#1: q    BLe       FALSE
#2: j    Bli       FALSE
#3: p BlaBLa        TRUE
1 голос
/ 31 марта 2019

Вот подход с .SDcols

require(dplyr)
require(data.table)
require(stringr)

DT <- DT[, key_ := do.call(paste, c(.SD, sep = "_")), .SDcols = 2:ncol(DT)]
DT <- DT[, has_blabla := as.integer(str_detect(key_, "BlaBla"))]

Первый создает ключ со всеми значениями столбца в строке, разделенными '_'. Затем следующий ищет его и помечает как двоичный файл. Поиск возвращает TRUE или FALSE, что при приведении к целому числу является двоичным.

1 голос
/ 31 марта 2019

Я бы использовал цикл for над списком и sapply над столбцами, используя .SDcols для исключения первого:

for (ii in seq_along(l)) {
  l[[ii]][ , .SDcols = -1L, 
          flag_BlaBLa := any(sapply(.SD, grepl, pattern = 'BlaBLa', fixed = TRUE))] 
}

Обратите внимание, что, поскольку вы на самом деле не используете какие-либорегулярное выражение fixed = TRUE является более эффективным вариантом использования grepl.Удалите fixed = TRUE, если шаблон, который вы пытаетесь обнаружить, действительно является регулярным выражением.

Если не все ваши столбцы являются строковыми столбцами, это можно сделать более эффективным, сделав .SDcols более строгим, например:

.SDcols = intersect(2:ncols(l[[ii]]), which(sapply(l[[ii]], is.character)))

(или, возможно, с использованием is.character(x) || is.factor(x))

1 голос
/ 31 марта 2019

Мы могли бы пройтись по списку, выбрать столбцы и проверить, есть ли хотя бы один "BlaBLa" в какой-либо строке и отметить строку TRUE / FALSE.

library(data.table)
lapply(l, function(x) x[, flag_BlaBLa := rowSums(x[,2:ncol(x)] == "BlaBLa") > 0])


l
#[[1]]
#   a      b      c flag_BlaBLa
#1: x BlaBLa    Bla        TRUE
#2: y    BLe    BLe       FALSE
#3: z    Bli BlaBLa        TRUE
#4: w BlaBLa    Blo        TRUE

#[[2]]
#   a      b flag_BlaBLa
#1: q    BLe       FALSE
#2: j    Bli       FALSE
#3: p BlaBLa        TRUE

EDIT

Если это не точное совпадение и нам нужно найти шаблон этой строки, нам также может понадобиться перебрать столбцы (аналогично @MichaelChirico), прежде чем брать rowSums

lapply(l, function(x) x[, flag_BlaBLa := rowSums(sapply(x[, 2:ncol(x)],
                      grepl, pattern = 'BlaBLa', fixed = TRUE)) > 0])


#[[1]]
#   a               b      c flag_BlaBLa
#1: x          BlaBLa    Bla        TRUE
#2: y             BLe    BLe       FALSE
#3: z             Bli BlaBLa        TRUE
#4: w BlaBLaSomething    Blo        TRUE

#[[2]]
#   a      b flag_BlaBLa
#1: q    BLe       FALSE
#2: j    Bli       FALSE
#3: p BlaBLa        TRUE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...