Подсчитать количество всех слов в строке - PullRequest
67 голосов
/ 19 января 2012

Есть ли функция для подсчета количества слов в строке?Например:

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

для возврата результата 7.

Ответы [ 17 ]

66 голосов
/ 19 января 2012

Используйте символ регулярного выражения \\W для сопоставления несловесных символов, используйте + для обозначения одного или нескольких в строке вместе с gregexpr для поиска всех совпадений в строке. Слова - это количество разделителей слов плюс 1.

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

Это не удастся с пустыми строками в начале или конце символьного вектора, когда «слово» не удовлетворяет понятию \\W не слова (можно работать с другими регулярными выражениями, \\S+ , [[:alpha:]] и т. Д., Но всегда будут крайние случаи с подходом регулярных выражений) и т. Д. Это, вероятно, более эффективно, чем strsplit решения, которые будут выделять память для каждого слова. Регулярные выражения описаны в ?regex.

Обновление Как отмечено в комментариях и в другом ответе @Andri, подход терпит неудачу с (ноль) и строками из одного слова, и с конечной пунктуацией

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

Многие из других ответов также терпят неудачу в этих или подобных (например, в нескольких пробелах) случаях. Я думаю, что оговорка моего ответа о «понятии одного слова» в исходном ответе охватывает проблемы с пунктуацией (решение: выберите другое регулярное выражение, например, [[:space:]]+), но проблемы с нулем и одним словом являются проблемой; Решение @ Andri не может различить ноль и одно слово. Поэтому, используя «позитивный» подход к поиску слов, можно

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

Ведущий к

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

Опять же, регулярное выражение может быть уточнено для различных понятий «слово».

Мне нравится использование gregexpr(), потому что оно эффективно использует память. В качестве альтернативы можно использовать strsplit() (например, @ user813966, но с регулярным выражением для разграничения слов) и использовать исходное понятие разграничения слов:

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

Для этого необходимо выделить новую память для каждого создаваемого слова и для промежуточного списка слов. Это может быть относительно дорого, когда данные «большие», но, вероятно, они эффективны и понятны для большинства целей.

40 голосов
/ 16 октября 2014

Самый простой способ будет выглядеть так:

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

... подсчет всех последовательностей на непробельных символах (\\S+).

Но как насчетмаленькая функция, которая позволяет нам также решить , какие слова мы хотели бы посчитать и какие работают также на целые векторы ?

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
23 голосов
/ 27 июня 2016

Я использую функцию str_count из библиотеки stringr с escape-последовательностью \w, которая представляет:

любой символ «слово» (буква, цифра или подчеркивание в текущем локаль: в режиме UTF-8 считаются только буквы и цифры ASCII)

Пример:

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

Из всех остальных 9 ответов, которые я смог протестировать, только два (Винсента Зоонекенда и Петермайснера) работали для всех представленных здесь материалов, но они также требуют stringr.

Но только это решение работает со всеми представленными на данный момент входными данными, а также с такими входными данными, как "foo+bar+baz~spam+eggs" или "Combien de mots sont dans cette phrase ?".

Benchmark:

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))

Выход:

6 10 10  8  9  9  7  6  6 11
15 голосов
/ 19 января 2012
str2 <- gsub(' {2,}',' ',str1)
length(strsplit(str2,' ')[[1]])

gsub(' {2,}',' ',str1) гарантирует, что все слова разделены одним пробелом, заменяя все вхождения двух или более пробелов одним пробелом.

strsplit(str,' ') разбивает предложение на каждый пробел и возвращает результат в виде списка. [[1]] извлекает вектор слов из этого списка. length подсчитывает, сколько слов.

> 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
14 голосов
/ 17 июля 2012

Вы можете использовать strsplit и sapply функции

sapply(strsplit(str1, " "), length)
13 голосов
/ 19 января 2012

Вы можете использовать str_match_all, с регулярным выражением, которое идентифицирует ваши слова.Следующее работает с начальным, конечным и дублированным пробелом.

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]])
11 голосов
/ 14 марта 2014

Попробуйте эту функцию из 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 
7 голосов
/ 20 марта 2016

Вы можете использовать wc функцию в библиотеке qdap :

> str1 <- "How many words are in this sentence"
> wc(str1)
[1] 7
6 голосов
/ 03 марта 2016

Вы можете удалить двойные пробелы и сосчитать число " " в строке, чтобы получить количество слов. Используйте stringr и rm_white { qdapRegex }

str_count(rm_white(s), " ") +1
5 голосов
/ 04 июля 2014

Попробуйте это

length(unlist(strsplit(str1," ")))
...