Есть ли функция для подсчета количества слов в строке? Например:
str1 <- "How many words are in this sentence"
чтобы вернуть результат 7.
Есть ли функция для подсчета количества слов в строке? Например:
str1 <- "How many words are in this sentence"
чтобы вернуть результат 7.
Ответы:
Вы можете использовать strsplit
и sapply
функции
sapply(strsplit(str1, " "), length)
lengths
функцию в базе R, которая находит длину каждого элемента:lengths(strsplot(str, " "))
Используйте символ регулярного выражения \\W
для сопоставления несловесных символов, используя +
для обозначения одного или нескольких в строке, а также gregexpr
для поиска всех совпадений в строке. Слова - это количество разделителей слов плюс 1.
lengths(gregexpr("\\W+", str1)) + 1
Это будет терпеть неудачу с пустыми строками в начале или в конце вектора символов, когда «слово» не удовлетворяет \\W
«s понятие несловообразующего (один может работать с другими регулярными выражениями \\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
При этом необходимо выделить новую память для каждого созданного слова и для промежуточного списка слов. Это может быть относительно дорого, когда данные «большие», но, вероятно, это эффективно и понятно для большинства целей.
str1 <- c('s ss sss ss', "asdf asd hello this is your life!"); sapply(gregexpr("\\W+", str1), length) + 1
возвращается 4
и 8
. Первое правильно, второе - слишком много. Думаю, дело в пунктуации.
sapply(gregexpr("\\W+", "word"), length) + 1
возвращает 2
Самый простой способ :
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
Я использую 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
'[\\w\']+'
(не можете проверить его, поэтому может применяться xkcd.com/1638 ), в противном случае я не уверен, что regex достаточно мощный, чтобы справиться с этим в общем случае :)
'\\w+(\'\\w{1,2})?'
может быть хорошим решением.
o'clock
и friggin'
вы могли бы \w+('\w*)?
(я не знаю, есть ли слова, начинающиеся с апострофа?). Чтобы дополнительно справиться с часами, вы можете попытаться сопоставить их, как \d?\d:\d\d|\w+('\w*)?
или сделать что-то еще более сложное, в зависимости от ваших потребностей. Но это все меньше и меньше о R и больше о том, как вы определяете слово, так что, может быть, вы можете опубликовать отдельный вопрос, чтобы охватить свои конкретные потребности?
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
Вы можете использовать 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]])
Попробуйте эту функцию из 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
Вы можете удалить двойные пробелы и подсчитать количество " "
в строке, чтобы получить количество слов. Используйте stringr и rm_white
{ qdapRegex }
str_count(rm_white(s), " ") +1
Решение 7 не дает правильного результата, если есть только одно слово. Вы должны не просто подсчитывать элементы в результате gregexpr (который равен -1, если там, где нет совпадений), но подсчитывать элементы> 0.
Ergo:
sapply(gregexpr("\\W+", str1), function(x) sum(x>0) ) + 1
str1
начинается или заканчивается символами, не являющимися словами. Если это вызывает беспокойство, эта версия будет искать только пробелы между словами:sapply(gregexpr("\\b\\W+\\b", str, perl=TRUE), function(x) sum(x>0) ) + 1
Я нашел следующую функцию и регулярное выражение, полезные для подсчета слов, особенно при работе с одинарными и двойными дефисами, где первый обычно не должен считаться разрывом слова, например, хорошо известный, привет-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
Со стрингером пакета можно также написать простой скрипт, который может перемещаться по вектору строк, например, через цикл for.
Скажем
df $ text
содержит вектор строк, которые мы хотим проанализировать. Сначала мы добавляем дополнительные столбцы в существующий фрейм данных 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
}
Результирующие столбцы: строки и символ будут содержать количество слов и символов, и это будет достигнуто за один раз для вектора строк.