Основываясь на 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 начинается с столбцов 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)
@samkart, это хорошая идея. Но как я могу создать эту конкатенированную переменную без явного упоминания имен столбцов, только диапазон столбцов 2:ncol(DT)
?
DT[, key_ := do.call(paste, c(.SD, sep = "_")), .SDcols = 2:ncol(DT)]
. Это может помочь вам в создании ключа, исключая первый столбец.
@samkart, Ницца, спасибо. Это работает. Потом сделал DT[, flag_BlaBLa := key_ %>% str_detect('BlaBLa')]
И получил правильный результат. Нет, мне нужно сделать эти два шага для каждого элемента списка l
. Ты знаешь как? В любом случае, пожалуйста, добавьте ответ в эти два комментария в качестве ответа
вы можете использовать цикл for для перебора списка l
. for (DTbl in l){ code }
Мы могли бы перебрать список, выбрать столбцы и проверить, есть ли хотя бы один «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
РЕДАКТИРОВАТЬ
Если это не точное совпадение, и нам нужно найти шаблон этой строки, нам также может понадобиться перебрать столбцы (аналогично @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
это красиво и лаконично. Но переменные, которые я исследую, могут иметь больше, чем просто работу. "БлаБЛа" также учитывается (мой первоначальный пример должен был отразить эту возможность). Поэтому там, где в приведенном выше коде есть «==», должна быть какая-то форма регулярного выражения.
Смотрите %like%
оператор
@LucasMation вы имеете в виду, что у вас могут быть другие варианты «BlaBLa» или других слов? Вы хотите точное совпадение разных слов или шаблонов совпадений?
@RonakShah, «BlaBLa» должен быть частью строк. См. обновленный пример выше.
@LucasMation Соответствующим образом обновил ответ.
Вот подход с .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
, которые при приведении к целому числу являются двоичными.
Я бы использовал цикл 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)
)
Мы можем указать интересующие столбцы в .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
возможно, вы можете создать ключ всех значений столбца, объединенных некоторым разделителем, за исключением первого столбца. Затем найдите строку в ключе.