文字列内のすべての単語の数を数える


82

文字列の単語数を数える機能はありますか?例えば:

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

7の結果を返します。


以下の@Martinの回答に基づいて、特定のテキスト文字列の1文あたりの単語数をカウントする関数countwordpersentence.Rを作成しました。複数の文を含む長いテキストの場合、それらすべての単語をカウントし、1文あたりの平均単語数と単語の総数を出力します。
Paul Rougieux 2015年

1
str_count(temp $ question1、 "")+1は、各単語がスペースで区切られていることがわかっている場合は簡単です。それはライブラリストリンガーの下にあります。
Vivek Srivastava 2017年

回答:


24

あなたは使用することができますstrsplitし、sapply機能

sapply(strsplit(str1, " "), length)

2
あなたは今、やや新しい使用できることだけ更新lengths:各要素の長さを発見し、ベースR内の関数、lengths(strsplot(str, " "))
ニック・ティアニー

これは非常に良い問題です。「word、word、word」のようなものがある場合、1が返されます
DimitriosZacharatos19年

71

正規表現記号\\Wを使用して単語以外の文字を照合し、を使用+して1つ以上の行を示しgregexpr、文字列内のすべての一致を検索します。単語は、単語区切り文字の数に1を加えたものです。

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

これは、「言葉」は満たしていないとき、文字ベクトルの先頭または末尾に空白文字列で失敗する\\Wの非単語(一方が他方の正規表現で仕事ができる、という考え方\\S+[[:alpha:]]などが、常にがあります正規表現アプローチによるエッジケース)などstrsplit。各単語にメモリを割り当てるソリューションよりも効率的である可能性があります。正規表現については、?regexます。

更新コメントと@Andriによる別の回答に記載されているように、アプローチは(ゼロ)と1単語の文字列、および末尾の句読点で失敗します

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

他の回答の多くも、これらまたは同様の(たとえば、複数のスペース)場合に失敗します。元の回答の「1つの単語の概念」に関する私の回答の警告は句読点の問題をカバーしていると思います(解決策:たとえば、別の正規表現を選択してください[[:space:]]+)が、0と1単語の場合は問題です。@Andriのソリューションでは、0語と1語を区別できません。したがって、単語を見つけるために「ポジティブ」なアプローチを取ることは、

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リターン48。最初は正解、2番目は多すぎます。句読点を数えていると思います。
フランシススマート

文末の句読点を数えていると思います。開始と終了の一致を無視するように正規表現に指示することをお勧めします(申し訳ありませんが、うまくいかないか、自分で修正します)。
フランシススマート

sapply(gregexpr("\\W+", "word"), length) + 12を返します
jaycode 2015年

ありがとう@ fsmart-句読点に関する懸念は、元の回答の「非単語の概念」に関する免責事項でカバーされていると思います。応答を更新しました。
マーティンモーガン

@jaycodeのおかげで、1つ(またはゼロ)の単語入力を数えられないことが問題になっています。元の回答を更新しました。
マーティンモーガン

49

最も簡単な方法は次のとおりです。

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

37

ライブラリのstr_count関数stringrを、次のようなエスケープシーケンス\wで使用します。

任意の「単語」文字(現在のロケールでは文字、数字、またはアンダースコア:UTF-8モードではASCII文字と数字のみが考慮されます)

例:

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

私がテストできた他の9つの回答のうち、これまでに提示されたすべての入力に対して機能したのは2つ(Vincent Zoonekyndとpetermeissnerによる)だけですが、必要なものもあり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

このアプローチは優れていますが、私がまだ直面している問題の1つは、アポストロフィを含む単語を二重にカウントすることです(たとえば、「I'm」または「John's」)。これに対処する方法はありますか?
スレドルセン

2
@Thredolsen単語区切り文字として扱う必要のあるアポストロフィがないことが確実な場合は、文字クラスを使用できます'[\\w\']+'(テストできないため、xkcd.com / 1638が適用される場合があります)。それ以外の場合はわかりません。正規表現は、一般的な場合にそれを処理するのに十分強力です:)
arekolek

1
それが適切な仮定であるかどうかはわかりませんが、アポストロフィの後に常に1文字または2文字しかない'\\w+(\'\\w{1,2})?'場合は、適切な解決策になる可能性があります。
arekolek

ありがとうございました。ほとんどの場合、どちらのアプローチも機能しますが、私の場合は、アポストロフィの後に2文字を超える単語が含まれているため、「[\\ w \ '] +」の方が適しているようです(例:時)。関連するフォローアップの質問:コロンの後に数字が直接続く場合も除外する方法はありますか(たとえば、「10:15」を2つではなく1つの単語として数えます)?
スレドルセン

2
このコメントでは、プレーンな正規表現構文を使用するので、例では追加のバックスラッシュが必要になります。のような単語をカバーするためにo'clockfriggin'あなたはそうすることができます\w+('\w*)?(アポストロフィで始まる単語があるかどうかはわかりませんか?)。さらに時間を処理するために、あなたはそれらを同じように一致\d?\d:\d\d|\w+('\w*)?させるか、あなたのニーズに応じてさらに複雑なことをすることを試みることができます。しかし、これはRについてではなく、単語をどのように定義するかについてのことなので、特定のニーズをカバーするために別の質問を投稿することができますか?
arekolek

15
str2 <- gsub(' {2,}',' ',str1)
length(strsplit(str2,' ')[[1]])

ザ・ gsub(' {2,}',' ',str1)作るには、必ずすべての単語は、一つのスペースで2つの以上のスペースのすべての出現箇所を置き換えることで、一つだけのスペースで区切られます。

ザ・ 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

タブ、新しい行、または改行できないスペースはどうですか?
bartektartanus 2017

5年前の答えを復活させる方法!'\ s'(Rでは '\\ s')を使用して、 ''ではなく任意のタイプの空白を含めます。
mathematical.coffee

私は自分の答えについての通知を受け取り、他の人を見て少し改善しました:D怒らないでください!:)PS。私も数学とコーヒーが好きです!
bartektartanus 2017

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

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 

6
@bartektartanusそれはいくつかの素晴らしい機能です!
ジョン

5
ありがとう:)このパッケージの残りの機能をチェックしてください!私はあなたが何か面白いものを見つけると確信しています:)どんなコメントも歓迎します!
bartektartanus 2014年

7

ライブラリqdapでwc関数を使用できます:

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

6

二重スペースを削除" "し、文字列内の数を数えて単語数を取得できます。stringrrm_white{ qdapRegex }を使用します

str_count(rm_white(s), " ") +1


5

またからstringiパッケージ、ストレートフォワード機能stri_count_words

stringi::stri_count_words(str1)
#[1] 7

4

単語が1つしかない場合、ソリューション7では正しい結果が得られません。gregexprの結果の要素(一致しない場合は-1)を数えるだけでなく、0より大きい要素を数える必要があります。

エルゴ:

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
アダム・ブラッドリー

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

単語の間にダブル/トリプルスペースを入れても問題ありません

他のすべての回答には、単語間に複数のスペースがあるという問題があります。


2

require(stringr)

非常に単純な関数を定義する

str_words <- function(sentence) {

  str_count(sentence, " ") + 1

}

小切手

str_words(This is a sentence with six words)

1

使用する nchar

文字列のベクトルが呼び出された場合 x

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

スペースの数を見つけて、1つ追加します


1

次の関数と正規表現は、特にシングルハイフンとダブルハイフンを処理する場合に単語カウントに役立つことがわかりました。前者は一般に単語の区切りとしてカウントされるべきではありません。たとえば、よく知られているhi-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

0

stringrパッケージ、1はまた、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
}

結果の列:文字列文字には単語と文字の数が含まれ、これは文字列のベクトルに対して一度に実行されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.