Подсчитайте количество всех слов в строке

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

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

чтобы вернуть результат 7.


person John    schedule 19.01.2012    source источник
comment
Основываясь на ответе @Martin ниже, я создал функцию countwordpersentence.R, которая подсчитывает количество слов на предложение в заданной текстовой строке. Для длинного текста, содержащего несколько предложений, он будет подсчитывать слова во всех из них и выводить среднее количество слов в предложении и общее количество слов.   -  person Paul Rougieux    schedule 30.10.2015
comment
str_count (temp $ question1,) +1 было бы легко, если бы вы знали, что каждое слово разделено пробелом. Он находится под библиотечным стрингером.   -  person Vivek Srivastava    schedule 27.05.2017


Ответы (17)


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

sapply(strsplit(str1, " "), length)
person AVSuresh    schedule 17.07.2012
comment
Просто обновление: теперь вы можете использовать несколько новую функцию lengths в базе R, которая определяет длину каждого элемента: lengths(strsplot(str, " ")) - person Nick Tierney; 13.05.2019
comment
это очень хорошо, проблема в том, что у вас есть что-то вроде слова, слова, слова, в этом случае оно вернет 1 - person Dimitrios Zacharatos; 12.12.2019

Используйте символ регулярного выражения \\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

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

person Martin Morgan    schedule 19.01.2012
comment
str1 <- c('s ss sss ss', "asdf asd hello this is your life!"); sapply(gregexpr("\\W+", str1), length) + 1 возвращает 4 и 8. Первое правильно, второе - слишком много. Я думаю, это счет знаков препинания. - person Francis Smart; 15.05.2015
comment
Я думаю, это счет знаков препинания в конце предложения. Совершенно уверен, что вы захотите указать регулярному выражению игнорировать начальные и конечные совпадения (извините, это бесполезно, иначе я бы исправил это сам). - person Francis Smart; 15.05.2015
comment
sapply(gregexpr("\\W+", "word"), length) + 1 возвращает 2 - person jaycode; 16.05.2015
comment
Спасибо @fsmart - я думаю, что беспокойство по поводу пунктуации покрывается отказом от ответственности о «понятии не-слова» в исходном ответе. Я обновил ответ. - person Martin Morgan; 18.05.2015
comment
Спасибо @jaycode, невозможность подсчитать 1 (или ноль) ввод слов является проблемой. Я обновил исходный ответ. - person Martin Morgan; 18.05.2015

Самый простой способ:

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
person petermeissner    schedule 16.10.2014

Я использую функцию 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 ?".

Контрольный показатель:

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
person arekolek    schedule 27.06.2016
comment
Этот подход превосходен, но одна проблема, с которой я все еще сталкиваюсь, заключается в том, что он дважды учитывает слова, содержащие апостроф (например, я или слова Джона). Есть ли способ решить эту проблему? - person Thredolsen; 26.03.2019
comment
@Thredolsen, если вы уверены, что не будет апострофов, которые следует рассматривать как разделители слов, вы можете использовать класс символов '[\\w\']+' (не можете его проверить, поэтому xkcd.com/1638 может применяться), иначе я не уверен, достаточно ли мощное регулярное выражение, чтобы справиться с этим в общем случае :) - person arekolek; 26.03.2019
comment
Не уверен, что это правильное предположение, но если после апострофа всегда есть только одна или две буквы, то '\\w+(\'\\w{1,2})?' может быть хорошим решением. - person arekolek; 26.03.2019
comment
Спасибо. Оба подхода работают по большей части, но '[\\ w \'] + 'в моем случае кажется лучше, поскольку некоторые слова содержат более двух символов после апострофа (например: o'clock). Связанный дополнительный вопрос: есть ли способ также исключить случаи, когда за двоеточием непосредственно следует числовой символ (например, считать '10: 15 'как одно слово, а не два)? - person Thredolsen; 27.03.2019
comment
В этом комментарии я собираюсь использовать простой синтаксис регулярных выражений, поэтому в примерах потребуются дополнительные обратные косые черты. Чтобы охватить такие слова, как o'clock и friggin', вы можете использовать \w+('\w*)? (я не знаю, есть ли слова, начинающиеся с апострофа?). Чтобы дополнительно обрабатывать часы, вы можете попытаться сопоставить их, например, \d?\d:\d\d|\w+('\w*)?, или сделать что-то еще более сложное в зависимости от ваших потребностей. Но это все меньше и меньше о R и больше о том, как вы определяете слово, так что, может быть, вы можете опубликовать отдельный вопрос, чтобы охватить свои конкретные потребности? - person arekolek; 27.03.2019
comment
@arekolek 'алло' алло! Согласитесь, это становится проблемой симантики. - person Slate; 28.03.2019

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
person mathematical.coffee    schedule 19.01.2012
comment
А как насчет табуляции, новых строк или неразрывных пробелов? - person bartektartanus; 20.02.2017
comment
Способ воскресить ответ пятилетней давности! Используйте '\ s' (в R, '\\ s') для включения любого типа пробелов, а не ''. - person mathematical.coffee; 21.02.2017
comment
Я получил уведомление о своем ответе и посмотрел на других, чтобы немного улучшить их: D Не сердитесь! :) PS. Я тоже люблю математику и кофе! - person bartektartanus; 21.02.2017

Вы можете использовать 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]])
person Vincent Zoonekynd    schedule 19.01.2012

Попробуйте эту функцию из пакета 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 
person bartektartanus    schedule 14.03.2014
comment
@bartektartanust, это хорошая функциональность! - person John; 14.03.2014
comment
Спасибо :) Проверьте остальные функции из этого пакета! Уверен, вы найдете что-то интересное :) Любые комментарии приветствуются! - person bartektartanus; 14.03.2014

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

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

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

str_count(rm_white(s), " ") +1
person Murali Menon    schedule 03.03.2016

Попробуй это

length(unlist(strsplit(str1," ")))
person Sangram    schedule 04.07.2014

Также из пакета stringi прямая функция stri_count_words

stringi::stri_count_words(str1)
#[1] 7
person Sotos    schedule 29.06.2018

Решение 7 не дает правильного результата, если есть только одно слово. Вы должны не просто подсчитывать элементы в результате gregexpr (который равен -1, если нет совпадений), но подсчитывать элементы> 0.

Ergo:

sapply(gregexpr("\\W+", str1), function(x) sum(x>0) ) + 1 
person Andri    schedule 19.12.2012
comment
Это все равно будет иметь проблемы, если str1 начинается или заканчивается символами, не являющимися словами. Если это вызывает беспокойство, эта версия будет искать только пробелы между словами: sapply(gregexpr("\\b\\W+\\b", str, perl=TRUE), function(x) sum(x>0) ) + 1 - person Adam Bradley; 01.07.2013

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

будет нормально с двойными / тройными пробелами между словами

Во всех других ответах есть проблемы с более чем одним пробелом между словами.

person CJunk    schedule 25.08.2017

требовать (строка)

Определите очень простую функцию

str_words <- function(sentence) {

  str_count(sentence, " ") + 1

}

Проверять

str_words(This is a sentence with six words)
person JDie    schedule 30.11.2018

Используйте 1_

если вектор строк называется x

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

Узнайте количество пробелов и добавьте один

person Jonny    schedule 06.01.2015

Я нашел следующую функцию и регулярное выражение, полезные для подсчета слов, особенно при работе с одинарными и двойными дефисами, где первый обычно не должен считаться разрывом слова, например, хорошо известный, привет-Fi; тогда как двойной дефис - это разделитель знаков препинания, который не ограничен пробелом, например, для замечаний в скобках.

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 - полезный пакет. Но в этом примере слишком много слов из-за дефиса.

stringi::stri_count_words(txt) #11 words
person Soren    schedule 28.03.2019

С помощью пакета stringr можно также написать простой скрипт, который может перемещаться по вектору строк, например, через цикл for.

Скажем

df $ текст

содержит вектор строк, которые мы хотим проанализировать. Сначала мы добавляем дополнительные столбцы в существующий фрейм данных df, как показано ниже:

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

Затем мы запускаем цикл for по вектору строк, как показано ниже:

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
}

Результирующие столбцы: строки и символ будут содержать количество слов и символов, и это будет достигнуто за один раз для вектора строк.

person Sandy    schedule 12.03.2019