通过子列表元素与字符向量的部分字符串匹配,使用基数 R 对 R 列表进行子集化

Subset R list by partial string match of sublist element against character vector, using base R

我的实际情况是 header 字符串和相应数据的组合列表 sub-lists;我希望将列表子集化为 return 列表 sub-lists ,即相同的结构,只包含 sub-lists 其 header 字符串包含与字符串匹配的字符串字符向量。

测试数据:

lets <- letters
x <- c(1,4,8,11,13,14,18,22,24)

ls <- list()
for (i in 1:9) {
  ls[[i]] <- list(hdr = paste(lets[x[i]:(x[i]+2)], collapse=""), 
                  data = seq(1,rnd[i]))
}

filt <- c("bc", "lm", "rs", "xy")

生成结果列表,如 return编辑者:

logical_match <- c(T, F, F, T, F, F, T, F, T) 
ls_result <- ls[logical_match]

所以我寻求的函数是:ls_result <- fn(ls, filt)

我看过:subset list by dataframe; ; ; subset list by logical condition; and, my favorite, extract sublist elements to array - 这使用了一些简洁的 purr 和 dplyr 解决方案,但不幸的是这些都不可行,因为我正在寻找一个基本的 R 解决方案来使部署更直接(当然,我欢迎扩展的 R 解决方案。

我猜 logical_match <- lapply(ls, fn, '$hdr', filt) 的一些变体是我要去的地方;我从 pmatch() 开始,想知道如何合并 grep,但我正在努力了解如何生成 logical_match 向量。

有人可以让我走上正轨吗?

编辑: 当 agrepl() 应用于真实数据时,这变得更加棘手; header 字符串 hdr 通常可能有 255 个字符长,而过滤器向量的字符串元素 filt 是16 个字符的顺序。 agrepl() max.distance 0.1 的参数需要调整到 0.94 和下面的示例为 0.96,非常紧凑。即使我使用此范围的下限,并将其应用于 ~360 个列表元素,函数 return 的总负荷为 non-matches.

> hdr <- "#CCHANNELSDI12-PTx|*|CCHANNELNO2|*|CDASA1570|*|CDASANAMEShenachieBU_1570|*|CTAGSODATSID|*|CTAGKEYWISKI_LIVE,ShenachieBU_1570,SDI12-PTx,Highres|*|LAYOUT(timestamp,value)|*|RINVAL-777|*|RSTATEW6|*|RTIMELVLhigh-resolution|*|TZEtc/GMT|*|ZDATE20210110130805|*|"

> filt <- c("ShenachieBU_1570", "Pitlochry_4056")

> agrepl(hdr, filt, max.distance = 0.94)
[1]  TRUE FALSE

你可以这样做:

Filter(function(x)any(agrepl(x$hdr,filt)), ls)

您可以将代码简化为:

Filter(function(x)grepl(paste0(filt, collapse = "|"), x$hdr), ls)

我们也可以

library(purrr)
library(stringr)
keep(ls, ~ str_detect(.x$hdr, str_c(filt, collapse = "|")))

-输出

#[[1]]
#[[1]]$hdr
#[1] "abc"

#[[1]]$data
#[1] 1


#[[2]]
#[[2]]$hdr
#[1] "klm"

#[[2]]$data
#[1] 1 2 3 4


#[[3]]
#[[3]]$hdr
#[1] "rst"

#[[3]]$data
#[1] 1 2 3 4 5 6 7


#[[4]]
#[[4]]$hdr
#[1] "xyz"

#[[4]]$data
#[1] 1 2 3 4 5 6 7 8 9