【问题标题】:Subset R list by partial string match of sublist element against character vector, using base R通过子列表元素与字符向量的部分字符串匹配,使用基数 R 子集 R 列表
【发布时间】:2021-04-18 20:57:11
【问题描述】:

我的实际案例是一个组合标题字符串和相应数据作为子列表的列表;我希望对列表进行子集化以返回子列表列表,即相同的结构,仅包含其标题字符串包含与字符向量中的字符串匹配的字符串的子列表。

测试数据:

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")

生成一个结果列表,由以下方式返回:

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

所以我寻求的函数是:ls_result

我看过:subset list by dataframe; partial match with %in%; nested sublist by condition; subset list by logical condition;而且,我最喜欢的extract sublist elements to array - 这使用了一些简洁的 purr 和 dplyr 解决方案,但不幸的是,这些都不可行,因为我正在寻找一个基本的 R 解决方案来使部署更加简单(我欢迎扩展的 R 解决方案,当然是为了兴趣)。

我猜测logical_match 的一些变体

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

编辑: 当 agrepl() 应用于真实数据时,这变得更加棘手;标头字符串 hdr 通常为 255 个字符长,而过滤器向量的字符串元素 filt 大约为 16 个字符。对于下面的示例,0.1 的默认 agrepl() max.distance 参数需要调整到 0.94 到 0.96 之间,这非常严格。即使我使用该范围的下限,并将其应用于 ~360 个列表元素,该函数也会返回总不匹配的负载。

> 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

【问题讨论】:

    标签: r string list vector subset


    【解决方案1】:

    你可以这样做:

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

    您可以将代码简化为:

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

    【讨论】:

    • 整洁! agrep1() 非常神秘。那么为什么会是agrepl(x$hdr,filt) 而不是agrepl(filt, x$hdr)filt 是要匹配的模式,x$hdr 是“寻找匹配的字符向量”。如果我反转似乎遵循文档的参数,则会生成错误:argument 'pattern' has length > 1 and only the first element will be used
    • 重新。 Filter(function(x)any(agrepl(x$hdr,filt)), ls) 所以 any() 就像一个向量 or;语义上:通过任何 hdr 值与 filt 模糊匹配过滤 ls
    【解决方案2】:

    我们也可以

    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
    

    【讨论】:

    • 整洁! "str_detect(string, pattern, negate = FALSE) : 向量化字符串和模式";那么为什么我们需要将 filt 向量折叠成单个字符串呢?
    • (from doc'n) keep()Filter() 类似,但参数顺序更方便,谓词函数.p 的求值更严格。我喜欢这个解决方案,但它不是我选择的解决方案,只是因为它使用了基础 R 之外的扩展库。谢谢。
    • @jack_sprat 关于您的查询,有一个条件是字符串和模式长度应该相同
    • 重新。相等的字符串和模式长度:谢谢 - 从文档中我看不出来!
    • @jack_sprat 你可以试试v1 &lt;- c("st1", "st2", "r12", "st1"); pat &lt;- c("st", "r1"); str_detect(v1, pat)#[1] TRUE FALSE FALSE FALSE,而如果它被粘贴,即str_detect(v1, str_c(pat, collapse="|"))#[1] TRUE TRUE TRUE TRUE 在第一种情况下,它是元素比较,因此较短的模式向量长度将不得不回收,即第一个元素将与 v1 的第一个元素进行比较,第二个与第二个元素进行比较,然后再与第一个元素,第二个元素进行比较
    猜你喜欢
    • 1970-01-01
    • 2016-10-18
    • 2021-04-26
    • 2020-05-02
    • 2021-12-07
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多