计算字符串向量中每个字母的数量

luk*_*123 3 r

我想生成一个向量,该向量具有向量中存在的字母表中所有26个数字的总数a.

a <- c("aabead", "dadfhhsa")
Run Code Online (Sandbox Code Playgroud)

例如,此向量中的a将等于5,b到1,d到2,z到0,x到0等.

A5C*_*2T1 10

您只需要这些功能,table并在以下strsplit方面提供一些帮助unlist:

table(unlist(strsplit(a, ""), use.names=FALSE))
#
# a b d e f h s 
# 5 1 3 1 1 2 1
Run Code Online (Sandbox Code Playgroud)
  • strsplit将字符串"爆炸"成单个字母.它list为矢量"a"中的每个字符串创建一个项目.
  • 由于输出strsplit是a list,你需要unlist先将它制成表格.在use.names = FALSE刚刚给出unlist的速度提升.
  • table,正如您现在可能已经猜到的那样,将输出列表.

如果你真的想要零值,那么你需要factor在内置的letters常量中得到一些帮助:

table(factor(unlist(strsplit(a, ""), use.names=FALSE), levels=letters))
#
# a b c d e f g h i j k l m n o p q r s t u v w x y z 
# 5 1 0 3 1 1 0 2 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 
Run Code Online (Sandbox Code Playgroud)

更新

处理这些类型的问题时,您必须迭代大量值,因此考虑如何解决问题非常重要.

例如,在接受的答案中,unlist(strsplit(...))被称为26次:每个字母一次.通过首先拆分和取消列出值,然后使用,您将发现显着的性能提升sapply.比较下面fun1afun2a下面的性能差异.

作为参考,我还对factor基于我的解决方案以及替代方案进行了基准测试tabulate.可以看出,这些比通过单个字母循环要快得多sapply.

library(stringi)
set.seed(1)
n <- 100000
a <- stri_rand_strings(n, sample(10, n, TRUE), "[a-z]")

fun1a <- function() sapply(letters, function(x) x<-sum(x==unlist(strsplit(a,""))))
fun1b <- function() {
  temp <- unlist(strsplit(a, ""))
  sapply(letters, function(x) {
    sum(x == temp)
  })
}
fun2 <- function() table(factor(unlist(strsplit(a, "", TRUE), use.names=FALSE), levels=letters))
fun3 <- function() {
  `names<-`(tabulate(
    factor(unlist(strsplit(a, "", TRUE), use.names = FALSE), 
           letters), nbins = 26), letters)
}

library(microbenchmark)
microbenchmark(fun1a(), fun1b(), fun2(), fun3(), times = 10)
# Unit: milliseconds
#     expr        min         lq       mean     median         uq        max neval
#  fun1a() 1025.45449 1177.90226 1189.49551 1190.11137 1238.66071 1352.05645    10
#  fun1b()  102.94881  114.08700  115.14852  115.87184  119.06776  124.64735    10
#   fun2()   53.46341   58.67832   67.50402   68.94933   70.71005   95.10771    10
#   fun3()   46.65357   49.79365   51.68536   51.55922   54.36390   57.07582    10
Run Code Online (Sandbox Code Playgroud)


Die*_*eno 5

你可以用这种方式使用lettersR内置向量

 > sapply(letters, function(x) x<-sum(x==unlist(strsplit(a,""))))
a b c d e f g h i j k l m n o p q r s t u v w x y z 
5 1 0 3 1 1 0 2 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
Run Code Online (Sandbox Code Playgroud)