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`