如果我有一串字符,例如
有没有办法让R来计算连续的
所以我想知道有多少次出现了3个
"AABBABBBAAAABBAAAABBBAABBBBABABB"
。有没有办法让R来计算连续的
A
的次数并说明每个长度有多少个?所以我想知道有多少次出现了3个
A
,有多少次只有一个A
,有多少次出现了2个A
等。table(rle(strsplit("AABBABBBAAAABBAAAABBBAABBBBABABB","")[[1]]))
给予
values
lengths A B
1 3 1
2 2 3
3 0 2
4 2 1
按照A列向下阅读,这意味着有3组长度为1的A连续出现,2组长度为2的A连续出现以及2组长度为4的A连续出现。
尝试
v1 <- scan(text=gsub('[^A]+', ',', str1), sep=',', what='', quiet=TRUE)
table(v1[nzchar(v1)])
# A AA AAAA
# 3 2 2
或者
library(stringi)
table(stri_extract_all_regex(str1, '[A]+')[[1]])
# A AA AAAA
# 3 2 2
set.seed(42)
x1 <- stri_rand_strings(1,1e7, pattern='[A-G]')
system.time(table(stri_split_regex(x1, "[^A]+", omit_empty = TRUE)))
# user system elapsed
# 0.829 0.002 0.831
system.time(table(stri_extract_all_regex(x1, '[A]+')[[1]]))
# user system elapsed
# 0.790 0.002 0.791
system.time(table(rle(strsplit(x1,"")[[1]])) )
# user system elapsed
# 30.230 1.243 31.523
system.time(table(strsplit(x1, "[^A]+")))
# user system elapsed
# 4.253 0.006 4.258
system.time(table(attr(gregexpr("A+",x1)[[1]], 'match.length')))
# user system elapsed
# 1.994 0.004 1.999
library(microbenchmark)
microbenchmark(david=table(stri_split_regex(x1, "[^A]+", omit_empty = TRUE)),
akrun= table(stri_extract_all_regex(x1, '[A]+')[[1]]),
david2 = table(strsplit(x1, "[^A]+")),
glen = table(rle(strsplit(x1,"")[[1]])),
plannapus = table(attr(gregexpr("A+",x1)[[1]], 'match.length')),
times=20L, unit='relative')
#Unit: relative
# expr min lq mean median uq max neval cld
# david 1.0000000 1.000000 1.000000 1.000000 1.0000000 1.000000 20 a
# akrun 0.7908313 1.023388 1.054670 1.336510 0.9903384 1.004711 20 a
# david2 4.9325256 5.461389 5.613516 6.207990 5.6647301 5.374668 20 c
# glen 14.9064240 15.975846 16.672339 20.570874 15.8710402 15.465140 20 d
#plannapus 2.5077719 3.123360 2.836338 3.557242 2.5689176 2.452964 20 b
str1 <- 'AABBABBBAAAABBAAAABBBAABBBBABABB'
strsplit
的方法。x <- "AABBABBBAAAABBAAAABBBAABBBBABABB"
table(strsplit(x, "[^A]+"))
# A AA AAAA
# 3 2 2
或者类似地使用 stringi
包
library(stringi)
table(stri_split_regex(x, "[^A]+", omit_empty = TRUE))
为了完整起见,这里介绍另一种提取正则表达式的方法,使用regmatches
和gregexpr
组合:
x <- "AABBABBBAAAABBAAAABBBAABBBBABABB"
table(regmatches(x,gregexpr("A+",x))[[1]])
# A AA AAAA
# 3 2 2
实际上,由于gregexpr
将捕获的子字符串长度保留为属性,因此甚至可以直接进行以下操作:
table(attr(gregexpr("A+",x)[[1]],'match.length'))
# 1 2 4
# 3 2 2
stringi
的技术(参见他的答案)或者使用base
的方式:paste(sample(c("A","B"),100,replace=TRUE),collapse="")
。 - plannapus
rle
通常很快,但strsplit
可能较慢。 - Glen_btable(nchar(strsplit(x, "[^A]+")[[1]]))
,因为 OP 只关心 "A"。 - Frankstrsplit
返回一个列表(在这种情况下,由于参数只包含一个元素,它返回一个包含一个元素的列表,该元素包含从拆分结果得到的字符向量)。我想要的是字符向量而不是它所包含的列表;[[1]]
是实现这一点的一种方式。 - Glen_b