从列表中重复出现的字符串模式实例中提取 header 数据
Extract header data from instances of string pattern in list, where there are repeated occurrences
我有一个列表:
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"
我想在小标题上显示结果,指示从中提取模式的来源(即列表 header)。由于在 $C 中重复出现 "bb",这会产生以下错误。
> 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
解决方案:
这是我自己解决问题的方法。
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
即使在 sub-string 中嵌入重复模式(如上),此方法也有效。
这变成了一个小问题,但以下工作:
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
这是一个tidyverse
想法,
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
这是在 base R 中执行此操作的一种方法。
# 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)))
unlist
returns 是所选项目的向量,use.names=FALSE 允许 data.frame
到 return 标准行名称而不是名称将由 unlist
生成。 data.frame
的第二个参数重复 tmp 中元素的名称以匹配匹配的元素。
这个returns
val src
1 bb A
2 bb C
3 bbc C
对于较长的字符串,您只想匹配两侧周围的 3 个字符,您可以将 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)))
对于第二个例子,这个returns
val src
1 yxybbxyx A
2 qedbbxyx C
3 bb C
我有一个列表:
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"
我想在小标题上显示结果,指示从中提取模式的来源(即列表 header)。由于在 $C 中重复出现 "bb",这会产生以下错误。
> 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
解决方案:
这是我自己解决问题的方法。
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
即使在 sub-string 中嵌入重复模式(如上),此方法也有效。
这变成了一个小问题,但以下工作:
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
这是一个tidyverse
想法,
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
这是在 base R 中执行此操作的一种方法。
# 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)))
unlist
returns 是所选项目的向量,use.names=FALSE 允许 data.frame
到 return 标准行名称而不是名称将由 unlist
生成。 data.frame
的第二个参数重复 tmp 中元素的名称以匹配匹配的元素。
这个returns
val src
1 bb A
2 bb C
3 bbc C
对于较长的字符串,您只想匹配两侧周围的 3 个字符,您可以将 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)))
对于第二个例子,这个returns
val src
1 yxybbxyx A
2 qedbbxyx C
3 bb C