grep из разных столбцов в r - PullRequest
0 голосов
/ 22 декабря 2018

У меня очень простой вопрос, но я не знаю, как получить желаемый результат.

У меня есть data.frame с несколькими столбцами, и я хочу получить значение для четырех из них, чтобы получитьподмножество data.frame.

Вот фиктивный пример

>df1
V1  V2           V3           V4           V5
 a  abc|ccc|ggg  ttt|ccc|shg  yyy|lmn|trs  abc|ggt|hgy
 b  atc|cjc|ggg  ttt|ccc|shg  abc|lmn|trs  abc|opq|sss
 c  auc|chc|ggg  abc|ccc|shg  gtc|lmn|trs  hyt|lki|ddd
 d  aoc|cfc|ggg  ttt|ccc|shg  yyy|lmn|trs  rmn|wde|tre

Я хотел бы подмножество data.frame на основе шаблона abc для столбцов V2,V3,V4,V5

Я знаю, что для одного столбца я могу сделать

 df2 <- df[grep('abc`, df$V1),]

Но как получить этот результат, используя несколько столбцов?

>df2
V1  V2           V3           V4           V5
 a  abc|ccc|ggg  ttt|ccc|shg  yyy|lmn|trs  abc|ggt|hgy
 b  atc|cjc|ggg  ttt|ccc|shg  abc|lmn|trs  abc|opq|sss
 c  auc|chc|ggg  abc|ccc|shg  gtc|lmn|trs  hyt|lki|ddd

Я не хочу получатьдополнительный столбец, как в этом вопросе grep один шаблон по нескольким столбцам , я хочу поместить в файл data.frame на основе шаблона

Спасибо

Ответы [ 4 ]

0 голосов
/ 23 декабря 2018

Вы можете попробовать:

df1 %>% filter_at(vars(V2:V5), any_vars(grepl("abc", .)))

Если вы хотите что-то быстрее, чем grepl(), используйте stringi::stri_detect_fixed()

big_df1 <- bind_rows(replicate(10e5, df1, simplify = FALSE))

mbm <- microbenchmark::microbenchmark(
  grepl = big_df1 %>% 
    filter_at(
      vars(V2:V5), 
      any_vars(grepl("abc", .))),
  stringi = big_df1 %>% 
    filter_at(
      vars(V2:V5), 
      any_vars(stringi::stri_detect_fixed(., "abc"))),
  times = 5L
)

, что дает:

#Unit: milliseconds
#    expr       min        lq      mean    median        uq      max neval
#   grepl 2603.2713 2613.4157 2665.3730 2646.4757 2709.6653 2754.037     5
# stringi  823.3735  832.9813  888.5228  901.2059  911.8805  973.173     5

enter image description here

0 голосов
/ 22 декабря 2018

Мы могли бы использовать sapply для циклического перебора столбцов, которые возвращали бы логический вектор для каждого элемента, указывающего, присутствует шаблон «abc» или нет, а затем отфильтровывали строки, в которых есть хотя бы один «abc»

cols <- c("V2", "V3", "V4", "V5")
df[rowSums(sapply(df[cols], function(x) grepl("abc", x))) > 0, ]

#   V1          V2          V3          V4          V5
#1   a abc|ccc|ggg ttt|ccc|shg yyy|lmn|trs abc|ggt|hgy
#2   b atc|cjc|ggg ttt|ccc|shg abc|lmn|trs abc|opq|sss
#3   c auc|chc|ggg abc|ccc|shg gtc|lmn|trs hyt|lki|ddd

Не совсем data.table эксперт, но следуя той же логике, которую мы можем сделать

library(data.table)
dt[rowSums(dt[, lapply(.SD, function(x) grepl("abc", x))]) > 0, ]


#   V1          V2          V3          V4          V5
#1:  a abc|ccc|ggg ttt|ccc|shg yyy|lmn|trs abc|ggt|hgy
#2:  b atc|cjc|ggg ttt|ccc|shg abc|lmn|trs abc|opq|sss
#3:  c auc|chc|ggg abc|ccc|shg gtc|lmn|trs hyt|lki|ddd
0 голосов
/ 22 декабря 2018

Вот несколько способов.

В первом sapply возвращает логическую матрицу с одной строкой на строку df1, используя grepl для указанного шаблона.Затем используйте rowSums, чтобы найти, какие строки имеют ИСТИНА.Наконец, мы подмножество этим.

Во втором мы вставляем вместе указанные столбцы df1, затем запускаем grepl и, наконец, подмножество этим.

Третий такой же, каквторой, но использует data.table.

Четвертый использует Reduce рабочий столбец за столбцом.

# 1
df1[ rowSums(sapply(df1[-1], grepl, pattern = "abc")) > 0, ]

# 2
df1[grepl("abc", do.call("paste", c(df1[-1]))), ]

# 3
library(data.table)
dt1 <- as.data.table(df1)
dt1[grepl("abc", do.call("paste", dt1[, -1]))]

# 4
df1[Reduce(function(x, y) x | grepl("abc", y), init = FALSE, df1), ]

Примечание

Входные данные в воспроизводимой форме:

Lines <- "V1  V2           V3           V4           V5
 a  abc|ccc|ggg  ttt|ccc|shg  yyy|lmn|trs  abc|ggt|hgy
 b  atc|cjc|ggg  ttt|ccc|shg  abc|lmn|trs  abc|opq|sss
 c  auc|chc|ggg  abc|ccc|shg  gtc|lmn|trs  hyt|lki|ddd
 d  aoc|cfc|ggg  ttt|ccc|shg  yyy|lmn|trs  rmn|wde|tre"
df1 <- read.table(text = Lines, header = TRUE, as.is = TRUE)
0 голосов
/ 22 декабря 2018

Просто используйте sapply(), который применяется grep() по столбцам.Значения должны быть перечислены и отсортированы, поэтому вы получите строки.

df1[sort(unique(unlist(sapply(df1, function(x) grep('abc', x))))), ]

#   V1          V2          V3          V4          V5
# 1  a abc|ccc|ggg ttt|ccc|shg yyy|lmn|trs abc|ggt|hgy
# 2  b atc|cjc|ggg ttt|ccc|shg abc|lmn|trs abc|opq|sss
# 3  c auc|chc|ggg abc|ccc|shg gtc|lmn|trs hyt|lki|ddd

Данные

df1 <- structure(list(V1 = structure(1:4, .Label = c("a", "b", "c", 
"d"), class = "factor"), V2 = structure(c(1L, 3L, 4L, 2L), .Label = c("abc|ccc|ggg", 
"aoc|cfc|ggg", "atc|cjc|ggg", "auc|chc|ggg"), class = "factor"), 
    V3 = structure(c(2L, 2L, 1L, 2L), .Label = c("abc|ccc|shg", 
    "ttt|ccc|shg"), class = "factor"), V4 = structure(c(3L, 1L, 
    2L, 3L), .Label = c("abc|lmn|trs", "gtc|lmn|trs", "yyy|lmn|trs"
    ), class = "factor"), V5 = structure(1:4, .Label = c("abc|ggt|hgy", 
    "abc|opq|sss", "hyt|lki|ddd", "rmn|wde|tre"), class = "factor")), class = "data.frame", row.names = c(NA, 
-4L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...