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.
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'est-à-dire c (2,1,0)).
La seule approche compliquée que j'ai gérée est la suivante:
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
Le paquet stringr 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("a", x)))
# [1] 2 1 0
nchar(as.character(q.data$string)) -nchar( gsub("a", "", q.data$string))
[1] 2 1 0
Notez que je force la variable facteur à caractère, avant de passer à nchar. Les fonctions regex semblent le faire en interne.
Voici des résultats de référence (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$string), 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")
Le paquetage stringi
fournit les fonctions stri_count
et stri_count_fixed
qui sont très rapides.
stringi::stri_count(q.data$string, fixed = "a")
# [1] 2 1 0
repère
Comparé à l'approche la plus rapide de la réponse de @ 42 ' et au fonction équivalente du paquet stringr
pour un vecteur de 30 000 éléments.
library(microbenchmark)
benchmark <- microbenchmark(
stringi = stringi::stri_count(test.data$string, fixed = "a"),
baseR = nchar(test.data$string) - nchar(gsub("a", "", test.data$string, fixed = TRUE)),
stringr = str_count(test.data$string, "a")
)
autoplot(benchmark)
data
q.data <- data.frame(number=1:3, string=c("greatgreat", "magic", "not"), stringsAsFactors = FALSE)
test.data <- q.data[rep(1:NROW(q.data), 10000),]
Le moyen le plus simple et le plus propre IMHO est:
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`
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
La question ci-dessous a été déplacée ici, mais il semble que cette page ne réponde pas directement à la question de Farah El. Comment trouver le numéro 1 sur 101 dans R
Donc, je vais écrire une réponse ici, juste au cas où.
library(magrittr)
n %>% # n is a number you'd like to inspect
as.character() %>%
str_count(pattern = "1")
Une variante de https://stackoverflow.com/a/12430764/589165 est
> nchar(gsub("[^a]", "", q.data$string))
[1] 2 1 0
s <- "aababacababaaathhhhhslsls jsjsjjsaa ghhaalll"
p <- "a"
s2 <- gsub(p,"",s)
numOcc <- nchar(s) - nchar(s2)
Peut ne pas être l'efficace mais résoudre mon objectif.
Vous pouvez simplement utiliser la division de chaîne
require(roperators)
my_strings <- c('Apple', banana', 'pear', 'melon')
my_strings %s/% 'a'
Ce qui vous donnera 1, 3, 1, 0. Vous pouvez également utiliser la division de chaîne avec des expressions régulières et des mots entiers.