从列表中的字符串模式实例中提取标题数据,其中重复出现

时间:2017-10-04 06:45:37

标签: r regex text-extraction tibble

我有一个清单:

lst <- list(A=c('aa', 'bb', 'cc'), B=c('ee', 'ff' ,'gg') ,C=c('aa', 'bb', 'bbc', 'dd'))

$A
[1] "aa" "bb" "cc"

$B
[1] "ee" "ff" "gg"

$C
[1] "aa"  "bb"  "bbc" "dd" 

我使用str_extract_all来收集符合特定模式的部分数据。

> data <- str_extract_all(lst, 'bb') %>% unlist() %>% compact()

[1] "bb" "bb" "bb"

我希望在一个tibble上显示结果,指示从中提取模式的源(即列表标题)。由于重复出现&#34; bb&#34;在$ C。

> tibble(data = data, src = names(lst[grep('bb', lst)]))
錯誤: Column `src` must be length 1 or 3, not 2

当没有重复出现时,代码工作正常。

> lst <- list(A=c('aa', 'bb', 'cc'), B=c('ee', 'ff', 'gg') ,C=c('aa', 'bb', 'cc', 'dd'))

$A
[1] "aa" "bb" "cc"

$B
[1] "ee" "ff" "gg"

$C
[1] "aa" "bb" "cc" "dd"

> data <- str_extract_all(lst, 'bb') %>% unlist() %>% compact()
> tibble(data = data, src = names(lst[grep('bb', lst)]))
# A tibble: 2 x 2
   data   src
  <chr> <chr>
1    bb     A
2    bb     C

我如何编码以避免错误?

# A tibble: 2 x 2
   data   src
  <chr> <chr>
1    bb     A
2    bb     C
3    bbc    C

在研究我的解决方案时,我认为我的问题最终归结为:

> pattern <- c('bb', 'ee')
> grep(paste(pattern, collapse="|"), lst)
[1] 1 2 3

grep()告诉我特定的字符串模式可以在我列表的第一个和第三个项目中找到。

我希望做的是在找到模式重现时让grep()重复项目编号。

[1] 1 2 3 3

我应该能够使用此模式生成源向量,并cbind()生成str_extract()结果:

> rslt <- tibble(data = c('bb', 'ee', 'bb', 'bbc'), src = c( 'A', 'B', 'C', 'C'))

# A tibble: 4 x 2
   data   src
  <chr> <chr>
1    bb     A
2    ee     B
3    bb     C
4   bbc     C

SOLUTION:

这是我自己解决问题的方法。

lst <- list(A=paste0('aa', str_dup("xy", 50), "bb", str_dup("ov", 50), "bb", str_dup("nm", 50), 'cc'), B=paste0('ee', 'ff' ,'gg') ,C=paste0('aa', str_dup("qed", 50), "bb", str_dup("sh", 50), 'bbc', 'dd'))

x <- str_count(lst, "bb") #Count instances to indicate repeats
x <- x[x != 0] #Remove the 0s
src.id <- mapply(rep, grep('bb', lst), x) %>% unlist() #Repeat source index to generate source vector
rslt <- tibble(str = str_extract_all(lst, "..bb..") %>% unlist() %>% compact(), src = names(lst[src.id]))

# A tibble: 4 x 2
     str   src
   <chr> <chr>
1 xybbov     A
2 ovbbnm     A
3 edbbsh     C
4 shbbcd     C

即使将重复的模式嵌入到子串中(如上所述),这仍然有效。

3 个答案:

答案 0 :(得分:1)

这变成了一点点kludge,但以下工作:

library(data.table)
rbindlist(lapply(lst, function(x) data.table(mtch = grep('bb', x, value = TRUE))),
          idcol = 'where')
#    where mtch
# 1:     A   bb
# 2:     C   bb
# 3:     C  bbc

答案 1 :(得分:1)

这是一个library(tidyverse) unlist(lst) %>% data.frame() %>% rename('v1' = '.') %>% rownames_to_column('v2') %>% filter(grepl('bb', v1)) %>% mutate(v2 = sub('\\d+', '', v2)) 想法,

  v2  v1
1  A  bb
2  C  bb
3  C bbc

给出,

$(document)

答案 2 :(得分:1)

这是在基础R中执行此操作的一种方法。

apache-tomee-plume-7.0.3

# get the matching values for each list element tmp <- lapply(lst, function(x) x[grep("bb", x)]) # build a data.frame data.frame(val=unlist(tmp, use.names=FALSE), src=rep(names(tmp), lengths(tmp))) 返回所选项目的向量,use.names = FALSE允许unlist返回标准行名称,而不是data.frame生成的名称。 unlist的第二个参数重复tmp中元素的名称以匹配匹配的元素。

返回

data.frame

对于较长的字符串,您只想匹配任意一方的周围3个字符,您可以将 val src 1 bb A 2 bb C 3 bbc C 替换为x[grep(...)],如下所示:

regmatches(regexpr)

对于第二个例子,这将返回

tmp <- lapply(lst, function(x) regmatches(x, regexpr("(...)?bb(...)?", x)))
# unchanged from above
data.frame(val=unlist(tmp, use.names=FALSE), src=rep(names(tmp), lengths(tmp)))