首页 > 解决方案 > 使用 data.table 跨多个列过滤字符串

问题描述

我有一个看起来像这样的数据集。

df <- tibble::tribble(
  ~name,           ~x,  ~y,              ~z,  
  "N/A",            1,   "testSmith",    -100, 
  "N A",            3,   "NOt available", -99,
  "test Smith",     NA,  "test Smith",    -98,
  "Not Available", -99, "25",             -101,
  "test Smith",    -98, "28",             -1)

我想创建一个新的data.table,将所有行都保留为字符串“test”。

最终的数据集应该是这样的

  name           x y              z
  <chr>      <dbl> <chr>      <dbl>
1 N/A            1 testSmith   -100
2 test Smith    NA test Smith   -98
3 test Smith   -98 28            -1

我可以像这样逐列做这个

setDT(df)[name%like%"test"|y%like%"test"]

这种方法的问题是我有数百个字符串变量,我想找到一种更紧凑的方法。我尝试了以下方法,但它们不起作用

chvar <- keep(trai,is.character)%>%names()
setDT(df)[chvar%like%"test"]#error
setDT(df)[(chvar)%like%"test"]#error
setDT(df)[.(chvar)%like%"test"]#empty dt

有人知道我如何以快速有效的方式做到这一点吗?

非常感谢你的帮助

标签: rdata.tabletidyverse

解决方案


data.table可以这样做:

library(data.table)

cols <- c('name', 'y')
setDT(df)

df[df[, Reduce(`|`, lapply(.SD, `%like%`, "test")), .SDcols = cols]]

#         name   x          y    z
#1:        N/A   1  testSmith -100
#2: test Smith  NA test Smith  -98
#3: test Smith -98         28   -1

在基础 R 中:

subset(df, Reduce(`|`, lapply(df[cols], function(x) grepl('test', x))))

dplyr

library(dplyr)
df %>% filter(Reduce(`|`, across(all_of(cols), ~grepl('test', .x))))

lapply/across返回所有列的TRUE/FALSE值列表。TRUE如果'test'存在和不存在,它将返回FALSE。当我们将它与 and 结合使用时Reduce|它只会给TRUE出行中至少有一个TRUE值。如果该行中的所有值都是FALSE它将返回FALSE。我们只选择那些至少有一个TRUE值的行。


推荐阅读