如何计算一列string每行中给定字符的出现次数?

我有一个data.frame其中某些variables包含一个文本string。 我希望统计每个string中给定字符的出现次数。

例:

q.data<-data.frame(number=1:3, string=c("greatgreat", "magic", "not")) 

我希望为q.data创build一个string中出现的“a”个数(即c(2,1,0))的新列。

我pipe理的唯一复杂的方法是:

 string.counter<-function(strings, pattern){ counts<-NULL for(i in 1:length(strings)){ counts[i]<-length(attr(gregexpr(pattern,strings[i])[[1]], "match.length")[attr(gregexpr(pattern,strings[i])[[1]], "match.length")>0]) } return(counts) } string.counter(strings=q.data$string, pattern="a") number string number.of.a 1 1 greatgreat 2 2 2 magic 1 3 3 not 0 

stringr包提供了str_count函数,这似乎是你所感兴趣的

 # Load your example data q.data<-data.frame(number=1:3, string=c("greatgreat", "magic", "not"), stringsAsFactors = F) library(stringr) # Count the number of 'a's in each element of string q.data$number.of.a <- str_count(q.data$string, "a") q.data # number string number.of.a #1 1 greatgreat 2 #2 2 magic 1 #3 3 not 0 

如果你不想离开基地R,这里有一个相当简洁和expression的可能性:

 x <- q.data$string sapply(regmatches(x, gregexpr("g", x)), length) # [1] 2 1 0 

更新:从R 3.2.0开始,可以使用lengths(x)作为更高效的replacesapply(x, length) 。 所以上面的代码可以简单的

 lengths(regmatches(x, gregexpr("g", x))) 
 nchar(as.character(q.data$string)) -nchar( gsub("a", "", q.data$string)) [1] 2 1 0 

请注意,在传递给nchar之前,我强制使用因子variables作为字符。 正则expression式函数似乎在内部执行。

这是基准testing结果(将testing的规模扩大到3000行)

  q.data<-q.data[rep(1:NROW(q.data), 1000),] str(q.data) 'data.frame': 3000 obs. of 3 variables: $ number : int 1 2 3 1 2 3 1 2 3 1 ... $ string : Factor w/ 3 levels "greatgreat","magic",..: 1 2 3 1 2 3 1 2 3 1 ... $ number.of.a: int 2 1 0 2 1 0 2 1 0 2 ... benchmark( Dason = { q.data$number.of.a <- str_count(as.character(q.data$string), "a") }, Tim = {resT <- sapply(as.character(q.data$string), function(x, letter = "a"){ sum(unlist(strsplit(x, split = "")) == letter) }) }, DWin = {resW <- nchar(as.character(q.data$string)) -nchar( gsub("a", "", q.data$string))}, Josh = {x <- sapply(regmatches(q.data$string, gregexpr("g",q.data$string )), length)}, replications=100) #----------------------- test replications elapsed relative user.self sys.self user.child sys.child 1 Dason 100 4.173 9.959427 2.985 1.204 0 0 3 DWin 100 0.419 1.000000 0.417 0.003 0 0 4 Josh 100 18.635 44.474940 17.883 0.827 0 0 2 Tim 100 3.705 8.842482 3.646 0.072 0 0 
 sum(charToRaw("abc.d.aa") == charToRaw('.')) 

是一个不错的select。

我确定有人可以做得更好,但是这个工作:

 sapply(as.character(q.data$string), function(x, letter = "a"){ sum(unlist(strsplit(x, split = "")) == letter) }) greatgreat magic not 2 1 0 

或者在一个函数中:

 countLetter <- function(charvec, letter){ sapply(charvec, function(x, letter){ sum(unlist(strsplit(x, split = "")) == letter) }, letter = letter) } countLetter(as.character(q.data$string),"a") 
 s <- "aababacababaaathhhhhslsls jsjsjjsaa ghhaalll" p <- "a" s2 <- gsub(p,"",s) numOcc <- nchar(s) - nchar(s2) 

可能不是有效的,但解决我的目的。

我像Amarjeet一样计数字符。 不过,我宁愿只用一行。

 HowManySpaces<-nchar(DF$string)-nchar(gsub(" ","",DF$string)) # count spaces in DF$string