web-dev-qa-db-fra.com

Compter le nombre de mots dans une chaîne

Existe-t-il une fonction permettant de compter le nombre de mots dans une chaîne? Par exemple:

str1 <- "How many words are in this sentence"

renvoyer un résultat de 7.

59
John

Vous pouvez utiliser les fonctions strsplit et sapply

sapply(strsplit(str1, " "), length)
9
AVSuresh

Utilisez le symbole d'expression régulière \\W pour faire correspondre les caractères autres que Word, en utilisant + pour en indiquer un ou plusieurs à la suite, ainsi que gregexpr pour rechercher toutes les correspondances dans une chaîne. Les mots sont le nombre de séparateurs de mots plus 1.

lengths(gregexpr("\\W+", str1)) + 1

Cela échouera avec des chaînes vides au début ou à la fin du vecteur de caractères, lorsqu'un "mot" ne correspond pas à la notion de non-mot de \\W (on pourrait travailler avec d'autres expressions régulières, \\S+, [[:alpha:]], etc., mais toujours être des cas Edge avec une approche regex), etc. Il est probablement plus efficace que les solutions strsplit, qui allouent de la mémoire pour chaque mot. Les expressions régulières sont décrites dans ?regex.

Update Comme indiqué dans les commentaires et dans une réponse différente de @Andri, l'approche échoue avec des chaînes (zéro) et un mot, et avec des signes de ponctuation à la fin.

str1 = c("", "x", "x y", "x y!" , "x y! z")
lengths(gregexpr("[A-z]\\W+", str1)) + 1L
# [1] 2 2 2 3 3

De nombreuses autres réponses échouent également dans ces cas ou dans des cas similaires (par exemple, des espaces multiples). Je pense que la réponse de ma réponse à la notion de "un mot" dans la réponse initiale couvre les problèmes de ponctuation (solution: choisissez une expression régulière différente, par exemple, [[:space:]]+), mais les cas zéro et un mot posent problème; La solution de @ Andri ne fait pas la distinction entre zéro et un mot. Donc, en adoptant une approche «positive» pour trouver des mots, on pourrait

sapply(gregexpr("[[:alpha:]]+", str1), function(x) sum(x > 0))

Menant à

sapply(gregexpr("[[:alpha:]]+", str1), function(x) sum(x > 0))
# [1] 0 1 2 2 3

Là encore, l'expression régulière peut être affinée pour différentes notions de «mot».

J'aime l'utilisation de gregexpr() car sa mémoire est efficace. Une alternative utilisant strsplit() (comme @ user813966, mais avec une expression régulière pour délimiter des mots) et utilisant la notion originale de délimitation de mots est:

lengths(strsplit(str1, "\\W+"))
# [1] 0 1 2 2 3

Cela doit allouer une nouvelle mémoire pour chaque mot créé et pour la liste de mots intermédiaire. Cela peut être relativement coûteux lorsque les données sont «volumineuses», mais elles sont probablement efficaces et compréhensibles dans la plupart des cas.

63
Martin Morgan

Le moyen le plus simple serait:

require(stringr)
str_count("one,   two three 4,,,, 5 6", "\\S+")

... en comptant toutes les séquences sur des caractères autres que des espaces (\\S+).

Mais qu'en est-il d'une petite fonction qui nous permet également de décider quel type de motsnous aimerions compter et quel fonctionne sur des vecteurs entiers aussi?

require(stringr)
nwords <- function(string, pseudo=F){
  ifelse( pseudo, 
          pattern <- "\\S+", 
          pattern <- "[[:alpha:]]+" 
        )
  str_count(string, pattern)
}

nwords("one,   two three 4,,,, 5 6")
# 3

nwords("one,   two three 4,,,, 5 6", pseudo=T)
# 6
34
petermeissner

J'utilise la fonction str_count de la bibliothèque stringr avec la séquence d'échappement \w qui représente:

tout caractère «mot» (lettre, chiffre ou trait de soulignement dans l'environnement local actuel: en mode UTF-8, seules les lettres et les chiffres ASCII sont pris en compte)

Exemple:

> str_count("How many words are in this sentence", '\\w+')
[1] 7

Sur les 9 autres réponses que j'ai pu tester, seules deux (de Vincent Zoonekynd et de petermeissner) ont fonctionné pour tous les intrants présentés ici jusqu'à présent, mais elles exigent également stringr.

Mais seule cette solution fonctionne avec toutes les entrées présentées jusqu'à présent, plus des entrées telles que "foo+bar+baz~spam+eggs" ou "Combien de mots sont dans cette phrase ?".

Référence:

library(stringr)

questions <-
  c(
    "", "x", "x y", "x y!", "x y! z",
    "foo+bar+baz~spam+eggs",
    "one,   two three 4,,,, 5 6",
    "How many words are in this sentence",
    "How  many words    are in this   sentence",
    "Combien de mots sont dans cette phrase ?",
    "
    Day after day, day after day,
    We stuck, nor breath nor motion;
    "
  )

answers <- c(0, 1, 2, 2, 3, 5, 6, 7, 7, 7, 12)

score <- function(f) sum(unlist(lapply(questions, f)) == answers)

funs <-
  c(
    function(s) sapply(gregexpr("\\W+", s), length) + 1,
    function(s) sapply(gregexpr("[[:alpha:]]+", s), function(x) sum(x > 0)),
    function(s) vapply(strsplit(s, "\\W+"), length, integer(1)),
    function(s) length(strsplit(gsub(' {2,}', ' ', s), ' ')[[1]]),
    function(s) length(str_match_all(s, "\\S+")[[1]]),
    function(s) str_count(s, "\\S+"),
    function(s) sapply(gregexpr("\\W+", s), function(x) sum(x > 0)) + 1,
    function(s) length(unlist(strsplit(s," "))),
    function(s) sapply(strsplit(s, " "), length),
    function(s) str_count(s, '\\w+')
  )

unlist(lapply(funs, score))

Sortie:

6 10 10  8  9  9  7  6  6 11
19
arekolek
str2 <- gsub(' {2,}',' ',str1)
length(strsplit(str2,' ')[[1]])

gsub(' {2,}',' ',str1) s'assure que tous les mots sont séparés par un seul espace en remplaçant toutes les occurrences de deux espaces ou plus par un seul espace.

strsplit(str,' ') divise la phrase à chaque espace et renvoie le résultat dans une liste. Le [[1]] saisit le vecteur de mots de cette liste. La length compte jusqu'à combien de mots.

> str1 <- "How many words are in this     sentence"
> str2 <- gsub(' {2,}',' ',str1)
> str2
[1] "How many words are in this sentence"
> strsplit(str2,' ')
[[1]]
[1] "How"      "many"     "words"    "are"      "in"       "this"     "sentence"
> strsplit(str2,' ')[[1]]
[1] "How"      "many"     "words"    "are"      "in"       "this"     "sentence"
> length(strsplit(str2,' ')[[1]])
[1] 7
15
mathematical.coffee

Vous pouvez utiliser str_match_all, avec une expression régulière qui identifierait vos mots . Ce qui suit fonctionne avec les espaces initial, final et dupliqué.

library(stringr)
s <-  "
  Day after day, day after day,
  We stuck, nor breath nor motion;
"
m <- str_match_all( s, "\\S+" )  # Sequences of non-spaces
length(m[[1]])
13
Vincent Zoonekynd

Essayez cette fonction du paquet stringi

   require(stringi)
   > s <- c("Lorem ipsum dolor sit amet, consectetur adipisicing elit.",
    +        "nibh augue, suscipit a, scelerisque sed, lacinia in, mi.",
    +        "Cras vel lorem. Etiam pellentesque aliquet tellus.",
    +        "")
    > stri_stats_latex(s)
        CharsWord CharsCmdEnvir    CharsWhite         Words          Cmds        Envirs 
              133             0            30            24             0             0 
11
bartektartanus

Vous pouvez utiliser wc function dans la bibliothèque qdap :

> str1 <- "How many words are in this sentence"
> wc(str1)
[1] 7
6
yuqian

Vous pouvez supprimer les doubles espaces et compter le nombre de " " dans la chaîne pour obtenir le nombre de mots. Utilisez stringr et rm_white { qdapRegex }

str_count(rm_white(s), " ") +1
6
Murali Menon

Essaye ça

length(unlist(strsplit(str1," ")))
5
Sangram

La solution 7 ne donne pas le résultat correct dans le cas où il y a juste un mot . Vous ne devez pas simplement compter les éléments dans le résultat de gregexpr (qui est -1 s'il n'y a pas de correspondance) mais compter les éléments> 0.

Ergo:

sapply(gregexpr("\\W+", str1), function(x) sum(x>0) ) + 1 
4
Andri

require (stringr)

Définir une fonction très simple

str_words <- function(sentence) {

  str_count(sentence, " ") + 1

}

Vérifier

str_words(This is a sentence with six words)
1
JDie

Également à partir du paquet stringi, la fonction directe stri_count_words

stringi::stri_count_words(str1)
#[1] 7
0
Sotos

J'ai trouvé les fonctions et expressions rationnelles suivantes utiles pour le décompte de mots, en particulier pour traiter les traits d'union simples à doubles, où les premiers ne doivent généralement pas être considérés comme une rupture de mot, par exemple, bien connue, hi-fi; alors que le double trait d'union est un délimiteur de ponctuation qui n'est pas délimité par un espace blanc - comme pour les remarques entre parenthèses.

txt <- "Don't you think e-mail is one Word--and not two!" #10 words
words <- function(txt) { 
length(attributes(gregexpr("(\\w|\\w\\-\\w|\\w\\'\\w)+",txt)[[1]])$match.length) 
}

words(txt) #10 words

Stringi est un paquet utile. Mais dans cet exemple, il compte trop de mots en raison d'un trait d'union.

stringi::stri_count_words(txt) #11 words
0
Soren

Utilisez nchar

si vecteur de chaînes s'appelle x

(nchar(x) - nchar(gsub(' ','',x))) + 1

Découvrez le nombre d'espaces puis ajoutez-en un

0
Jonny

Avec stringr package, on peut également écrire un script simple qui pourrait traverser un vecteur de chaînes, par exemple via une boucle for.

Disons

df $ text

contient un vecteur de chaînes que nous sommes intéressés à analyser. Premièrement, nous ajoutons des colonnes à la base de données existante df comme ci-dessous:

df$strings    = as.integer(NA)
df$characters = as.integer(NA)

Ensuite, nous courons une boucle for sur le vecteur de chaînes comme ci-dessous:

for (i in 1:nrow(df)) 
{
   df$strings[i]    = str_count(df$text[i], '\\S+') # counts the strings
   df$characters[i] = str_count(df$text[i])         # counts the characters & spaces
}

Les colonnes résultantes: chaînes et caractère contiendront le nombre de mots et de caractères, ce qui sera réalisé en une fois pour un vecteur de chaînes.

0
Sadiaz
require(stringr)
str_count(x,"\\w+")

ira bien avec des espaces doubles/triples entre les mots

Toutes les autres réponses ont des problèmes avec plus d'un espace entre les mots. 

0
CJunk