Comment calculer le nombre d’occurrences d’un caractère donné dans chaque ligne d’une colonne de chaînes?

J’ai un data.frame dans lequel certaines variables contiennent une chaîne de texte. Je souhaite compter le nombre d’occurrences d’un caractère donné dans chaque chaîne individuelle.

Exemple:

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

Je souhaite créer une nouvelle colonne pour q.data avec le nombre d’occurrences de “a” dans la chaîne (c.-à-d. C (2,1,0)).

La seule approche compliquée que j’ai gérée est la suivante:

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

Le paquet ssortingngr fournit la fonction str_count qui semble faire ce qui vous intéresse

 # 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 

Si vous ne voulez pas quitter la base R, voici une possibilité assez succincte et expressive:

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

Notez que je contrains la variable factor à character, avant de passer à nchar. Les fonctions regex semblent le faire en interne.

Voici les résultats de tests (avec une taille de test augmentée à 3000 lignes)

  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('.')) 

est une bonne option.

Je suis sûr que quelqu’un peut faire mieux, mais cela fonctionne:

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

ou dans une fonction:

 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) 

Peut ne pas être efficace mais résoudre mon objective.

Je compte les personnages de la même manière que Amarjeet. Cependant, je préfère le faire en une seule ligne.

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

Le moyen le plus simple et le plus propre est IMHO:

 q.data$number.of.a <- lengths(gregexpr('a', q.data$string)) # number string number.of.a` #1 1 greatgreat 2` #2 2 magic 1` #3 3 not 0`