通过子列表元素与字符向量的部分字符串匹配,使用基数 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
我的实际情况是 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;
我猜 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