¿Existe una función para contar el número de palabras en una cadena? Por ejemplo:
str1 <- "How many words are in this sentence"
para devolver un resultado de 7.
¿Existe una función para contar el número de palabras en una cadena? Por ejemplo:
str1 <- "How many words are in this sentence"
para devolver un resultado de 7.
Respuestas:
Puede utilizar strsplit
y sapply
funciones
sapply(strsplit(str1, " "), length)
lengths
función algo nueva en la base R, que encuentra la longitud de cada elemento:lengths(strsplot(str, " "))
Utilice el símbolo de expresión regular \\W
para hacer coincidir los caracteres que no son palabras, utilizando +
para indicar uno o más en una fila, junto con gregexpr
para buscar todas las coincidencias en una cadena. Las palabras son el número de separadores de palabras más 1.
lengths(gregexpr("\\W+", str1)) + 1
Este fallará con cadenas en blanco al principio o al final del vector de caracteres, cuando una "palabra" no satisface \\W
's noción de no-palabra (se podría trabajar con otras expresiones regulares, \\S+
, [[:alpha:]]
, etc., pero siempre habrá ser casos extremos con un enfoque de expresiones regulares), etc. Es probable que sea más eficiente que las strsplit
soluciones, que asignarán memoria para cada palabra. Las expresiones regulares se describen en ?regex
.
Actualización Como se señaló en los comentarios y en una respuesta diferente de @Andri, el enfoque falla con (cero) y cadenas de una palabra, y con puntuación final
str1 = c("", "x", "x y", "x y!" , "x y! z")
lengths(gregexpr("[A-z]\\W+", str1)) + 1L
# [1] 2 2 2 3 3
Muchas de las otras respuestas también fallan en estos o casos similares (p. Ej., Espacios múltiples). Creo que la advertencia de mi respuesta sobre la "noción de una palabra" en la respuesta original cubre problemas con la puntuación (solución: elija una expresión regular diferente, por ejemplo, [[:space:]]+
), pero los casos de una palabra y cero son un problema; La solución de @ Andri no distingue entre cero y una palabra. Así que adoptar un enfoque 'positivo' para encontrar palabras que uno podría
sapply(gregexpr("[[:alpha:]]+", str1), function(x) sum(x > 0))
Llevando a
sapply(gregexpr("[[:alpha:]]+", str1), function(x) sum(x > 0))
# [1] 0 1 2 2 3
Nuevamente, la expresión regular podría refinarse para diferentes nociones de "palabra".
Me gusta el uso de gregexpr()
porque es eficiente en la memoria. Una alternativa al usar strsplit()
(como @ user813966, pero con una expresión regular para delimitar palabras) y hacer uso de la noción original de delimitar palabras es
lengths(strsplit(str1, "\\W+"))
# [1] 0 1 2 2 3
Esto necesita asignar nueva memoria para cada palabra que se crea y para la lista intermedia de palabras. Esto podría resultar relativamente caro cuando los datos son "grandes", pero probablemente sea eficaz y comprensible para la mayoría de los propósitos.
str1 <- c('s ss sss ss', "asdf asd hello this is your life!"); sapply(gregexpr("\\W+", str1), length) + 1
devuelve 4
y 8
. Primero correcto, segundo demasiado. Creo que está contando la puntuación.
sapply(gregexpr("\\W+", "word"), length) + 1
devuelve 2
La forma más sencilla sería:
require(stringr)
str_count("one, two three 4,,,, 5 6", "\\S+")
... contando todas las secuencias en caracteres sin espacios ( \\S+
).
Pero, ¿qué pasa con una pequeña función que nos permite también decidir qué tipo de palabras nos gustaría contar y cuáles funcionan también en vectores completos ?
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
Uso la str_count
función de la stringr
biblioteca con la secuencia de escape\w
que representa:
cualquier carácter de 'palabra' (letra, dígito o subrayado en la configuración regional actual: en el modo UTF-8 solo se consideran letras y dígitos ASCII)
Ejemplo:
> str_count("How many words are in this sentence", '\\w+')
[1] 7
De todas las otras 9 respuestas que pude probar, solo dos (por Vincent Zoonekynd y por petermeissner) funcionaron para todas las entradas presentadas aquí hasta ahora, pero también requieren stringr
.
Pero solo esta solución funciona con todas las entradas presentadas hasta ahora, más entradas como "foo+bar+baz~spam+eggs"
o "Combien de mots sont dans cette phrase ?"
.
Punto de referencia:
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))
Salida:
6 10 10 8 9 9 7 6 6 11
'[\\w\']+'
(no se puede probar, por lo que puede aplicarse xkcd.com/1638 ); de lo contrario, no estoy seguro de si regex es lo suficientemente potente como para manejarlo en el caso general :)
'\\w+(\'\\w{1,2})?'
podría ser una buena solución.
o'clock
y friggin'
podrías hacer \w+('\w*)?
(no sé si hay palabras que comiencen con apóstrofe). Para manejar adicionalmente las horas, puede intentar hacerlas coincidir \d?\d:\d\d|\w+('\w*)?
o hacer algo aún más complicado según sus necesidades. Pero esto se trata cada vez menos de R y más de cómo define una palabra, por lo que tal vez pueda publicar una pregunta separada para cubrir sus necesidades específicas.
str2 <- gsub(' {2,}',' ',str1)
length(strsplit(str2,' ')[[1]])
Se gsub(' {2,}',' ',str1)
asegura de que todas las palabras estén separadas por un solo espacio, reemplazando todas las apariciones de dos o más espacios con un espacio.
El strsplit(str,' ')
divide la frase en cada espacio y devuelve el resultado en una lista. El [[1]]
toma el vector de palabras de esa lista. La length
cuenta hasta cuántas palabras.
> 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
Puede usar str_match_all
, con una expresión regular que identifique sus palabras. A continuación se trabaja con espacios iniciales, finales y duplicados.
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]])
Prueba esta función del stringi
paquete
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
Puede eliminar los espacios dobles y contar el número de " "
en la cadena para obtener el recuento de palabras. Utilice stringr y rm_white
{ qdapRegex }
str_count(rm_white(s), " ") +1
La solución 7 no da el resultado correcto en el caso de que solo haya una palabra. No solo debe contar los elementos en el resultado de gregexpr (que es -1 si no coincide), sino contar los elementos> 0.
Es decir:
sapply(gregexpr("\\W+", str1), function(x) sum(x>0) ) + 1
str1
comienza o termina con caracteres que no son palabras. Si eso es una preocupación, esta versión solo buscará espacios entre palabras:sapply(gregexpr("\\b\\W+\\b", str, perl=TRUE), function(x) sum(x>0) ) + 1
He encontrado que la siguiente función y expresión regular son útiles para el recuento de palabras, especialmente al tratar con guiones simples o dobles, donde el primero generalmente no debería contar como un salto de palabra, por ejemplo, bien conocido, de alta fidelidad; mientras que el guión doble es un delimitador de puntuación que no está delimitado por espacios en blanco, como ocurre con los comentarios entre paréntesis.
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 es un paquete útil. Pero cuenta en exceso las palabras en este ejemplo debido al guión.
stringi::stri_count_words(txt) #11 words
Con stringr paquete , también se puede escribir un script simple que pueda atravesar un vector de cadenas, por ejemplo, a través de un bucle for.
Digamos
df $ texto
contiene un vector de cadenas que nos interesa analizar. Primero, agregamos columnas adicionales al marco de datos existente df como se muestra a continuación:
df$strings = as.integer(NA)
df$characters = as.integer(NA)
Luego ejecutamos un bucle for sobre el vector de cadenas de la siguiente manera:
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
}
Las columnas resultantes: cadenas y carácter contendrán los recuentos de palabras y caracteres y esto se logrará de una sola vez para un vector de cadenas.