96

有没有计算字符串中单词数的函数?例如:

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

返回结果 7。

4

18 回答 18

76

使用正则表达式符号\\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

这需要为每个创建的单词和中间的单词列表分配新的内存。当数据“大”时,这可能会相对昂贵,但对于大多数目的来说,它可能是有效且易于理解的。

于 2012-01-19T02:15:16.663 回答
57

最简单的方法是:

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
于 2014-10-16T14:22:39.203 回答
48

我将库中的str_count函数与转义序列一起使用,该转义序列表示:stringr\w

任何“单词”字符(当前语言环境中的字母、数字或下划线:在 UTF-8 模式下,仅考虑 ASCII 字母和数字)

例子:

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

在我能够测试的所有其他 9 个答案中,只有两个(Vincent Zoonekynd 和 petermeissner)适用于到目前为止此处提供的所有输入,但它们也需要stringr.

但只有此解决方案适用于目前提供的所有输入,以及诸如"foo+bar+baz~spam+eggs"or之类的输入"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))

输出(11 是可能的最高分):

6 10 10  8  9  9  7  6  6 11
于 2016-06-27T15:37:16.270 回答
29

您可以使用strsplitsapply功能

sapply(strsplit(str1, " "), length)
于 2012-07-17T04:46:15.883 回答
15
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
于 2012-01-19T02:01:40.223 回答
13

您可以将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]])
于 2012-01-19T02:16:22.643 回答
11

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 
于 2014-03-14T09:54:42.207 回答
7

您可以在库qdap中使用wc函数:

> str1 <- "How many words are in this sentence"
> wc(str1)
[1] 7
于 2016-03-20T15:51:04.130 回答
6

您可以删除双空格并计算" "字符串中的数量以获取字数。使用 stringrrm_white{ qdapRegex }

str_count(rm_white(s), " ") +1
于 2016-03-03T09:16:23.987 回答
5

试试这个

length(unlist(strsplit(str1," ")))
于 2014-07-04T06:38:32.883 回答
5

同样来自stringi包,直接功能stri_count_words

stringi::stri_count_words(str1)
#[1] 7
于 2018-06-29T10:05:50.800 回答
4

在只有一个单词的情况下,解决方案 7 不会给出正确的结果。您不应该只计算 gregexpr 结果中的元素(如果不匹配,则为 -1),而是计算元素 > 0。

尔格:

sapply(gregexpr("\\W+", str1), function(x) sum(x>0) ) + 1 
于 2012-12-19T09:14:48.493 回答
4
require(stringr)
str_count(x,"\\w+")

单词之间有双/三空格会很好

所有其他答案都存在单词之间不止一个空格的问题。

于 2017-08-25T22:45:27.870 回答
3

要求(字符串)

定义一个非常简单的函数

str_words <- function(sentence) {

  str_count(sentence, " ") + 1

}

查看

str_words(This is a sentence with six words)
于 2018-11-30T18:37:32.720 回答
2

您可以使用字符串函数 str_split() 和 boundary(),它们将识别单词的边界,同时忽略标点符号和任何额外的空格

sapply(str_split("It's 12 o'clock already", boundary("word")), length)
#[1] 4
sapply(str_split("  It's  >12  o'clock already ?! ", boundary("word")), length)
#[1] 4
于 2021-10-19T06:30:57.820 回答
1

采用nchar

如果调用字符串向量x

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

找出空格数然后加一个

于 2015-01-06T16:50:53.617 回答
1

使用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
}

结果列:字符串字符将包含单词和字符的计数,这将一次性实现字符串向量。

于 2019-03-12T00:32:41.967 回答
1

我发现以下函数和正则表达式对字数统计很有用,尤其是在处理单连字符和双连字符时,前者通常不应该算作分词,例如,众所周知的、高保真;而双连字符是不受空格限制的标点分隔符 - 例如用于括号注释。

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
于 2019-03-28T11:15:56.937 回答