医療職からデータサイエンティストへ

統計学、機械学習に関する記事をまとめています。

Rでtweetをテキストマイニング:ワードクラウドと共起ネットワーク

テキストマイニング は文字列を対象したデータマイニング手法で、単語の出現頻度、出現タイミングなどを集計する簡単なものから、機械学習を用いてクラス分類する高度なものまで様々な解析手法があります。

今回はそんなテキストマイニング の中でも、単語の出現頻度をわかりやすく可視化するワードクラウドと、どの単語と一緒に出現しやすいかを調べる共起語、それを可視化する共起ネットワークを使って、私自身のtweetを解析したいと思います。 今回は以下の2冊を参考にしています。

Rによるやさしいテキストマイニング

Rによるやさしいテキストマイニング

Rによるやさしいテキストマイニング [活用事例編]

Rによるやさしいテキストマイニング [活用事例編]

下準備

Rで日本語テキストマイニング を行うための有名なパッケージには{RMeCab}があります。こちらは、あらかじめお使いのPCにインストールする必要があります。こちらから指示にしたがってインストールしてください。

install - rmecab

インストール後Rを立ち上げて、こんな感じになれば成功です。

install.packages("RMeCab", repos = "http://rmecab.jp/R", type = "source")
library(RMeCab)
library(tidyverse)

res <- RMeCabC("今回はテキストマイニングの記事です。")
>unlist(res)
    名詞         助詞         名詞         名詞         助詞 
      "今回"         "は"   "テキスト" "マイニング"         "の" 
        名詞       助動詞         記号 
      "記事"       "です"         "。" 

Tweetの読み込み

{RMecab}の次はTweetを読み込むためのパッケージ{rtweet}をインストールしておきます。以前はTwitterのAPI設定などが必要でしたが、この{rtweet}はそんなものは必要なく、簡単にTweetを取得できます。 ただ、twitterのアプリ自体の登録は必要で、初めて使うときには連携の承認を求められます。もし、Twitterを利用されていない方は、今回のデータcsvをこちらに置いておきますので、使ってみてください。

※日々tweetしていますので、{rtweet}を使う方は本記事と結果が異なることをご了承ください。

install.packages("rtweet")
library(rtweet)

res <- search_tweets("テキストマイニング",n=100,account_lang="ja")
>res %>% head()
# A tibble: 6 x 90
  user_id status_id created_at          screen_name text 
  <chr>   <chr>     <dttm>              <chr>       <chr>
1 781888116453862019-08-22 14:03:39 ishikaku_5… テキスト…
2 161817116446732019-08-22 09:20:16 jinrobiz    チャット…
3 307623116445172019-08-22 08:18:28 kyn02666    "結構W…
4 109839… 11644021… 2019-08-22 05:01:12 twiTamori   "ツイッ…
5 109839116400642019-08-21 02:48:59 twiTamori   "@to…
6 109839… 11640297… 2019-08-21 04:21:32 twiTamori   "@to…

試しに"テキストマイニング "の文字が入る最新tweet100件を取得してみました。取得できる情報には、時刻やtweet内容だけでなく、いいねの数や発信場所なども取得できます。{rtweet}には他にも様々な機能があるので、興味ある方は是非調べてみてください。経度緯度を指定して、特定の地域のtweetを取得できたりもします。

Tweetをテキストマイニング

さて、早速私のTweetを取得してテキストマイニング してみましょう。まずはTweetのテキストから、余分な文字などを消していきます。

#medi_data0826のタイムラインを最大400行取得
tl <- get_timeline("medi_data0826", n = 400) 
#もしくはCSVの読み込み
#tl <- read_csv("tweet_text.csv")

#余分な文字の消去
tl2 <- tl %>% 
  select(created_at,text) %>%#rtweetを使った方のみ
  mutate(text=str_remove_all(text,"https?://.*[a-zA-Z0-9]"),#URL
         text=str_remove_all(text,"\n"),#改行
         text=str_remove_all(text,"[:punct:]"),#句読点
         text=str_remove_all(text,"\\^"),#顔文字の目
         text=str_remove_all(text,"~"),#ニョロニョロ
         text=str_remove_all(text,"[0-9]"),#単独の数字 
         text=str_remove_all(text,"@[a-zA-Z0-9]*")))#返信のタグ

{RMeCab}にはテキストマイニング するための関数がいくつかありますが、今回はその中の二つを紹介します。まずは、データフレーム内のテキストを品詞分解してくれるRMeCabDF{RMeCab}です。

res <- tl2%>% 
  as.data.frame() %>% 
  RMeCabDF(2)

> unlist(res) %>% head(5)
    名詞     助詞     名詞     名詞     助詞 
    "今"     "の" "ところ" "データ"     "の"

RMeCabDF{RMeCab}では、データフレームを渡して、テキストのあるカラムを指定します。注意点としては、tibble型だとうまく変換できないので、通常のデータフレーム型に変換する必要があります。結果は各行ごとに品詞分解を行ったリストで返ってくるので、集計の際はunlist{base}を使ってくだいさいね。

このまま解析を進めてもいいのですが、RMeCabDF{RMeCab}は実行速度が遅いのもあり、これは紹介に留めてもう一つの関数RMeCabFreq{RMeCab}を使って解析を行っていきます。RMeCabFreq{RMeCab}は品詞分解だけでなく、頻度の集計まで行ってくれます。しかし、データフレームの形ではなく、ファイルを渡す必要があるので、解析前には一手間必要です。

#一時的なファイルを作り、テキストを書き出す

temp <- tempfile()
tl2 %>% 
  pull(text) %>%
  write(file=temp)

これで準備完了です。あとはこのtempRMeCabFreq{RMeCab}に渡します。

res_freq <- RMeCabFreq(temp) 

> res_freq %>% head()
        Term    Info1 Info2 Freq
1 そうですね フィラー     *    1
2     なんか フィラー     *    2
3     あえて     副詞  一般    1
4   いい加減     副詞  一般    1
5     いかに     副詞  一般    4
6       いざ     副詞  一般    4

結果はデータフレームで返ってきて、品詞分解後の単語(Term)、品詞(Info1)、品詞のさらに細かい分類(Info2)、頻度(Freq)がカラムとなります。ここから、名詞と形容詞のみを抜き出し、出現頻度Top20をグラフにしてみましょう。

res_freq%>% 
  filter(Info1=="名詞"|Info1=="形容詞") %>%
  arrange(desc(Freq)) %>% 
  head(20) %>% 
  ggplot()+
  geom_bar(aes(x=reorder(Term,Freq),y=Freq,fill=Info1),stat="identity")+
  coord_flip() + 
  theme(axis.title = element_blank())

テキストマイニング

単語頻度は"データ"が一番多くなっており、Top20には名詞しかないようです。さあ、いよいよこれをワードクラウドにしていきます。ワードクラウドとは説明するよりも見た方が早いので、早速作ってみましょう。ワードクラウド作成には{wordcloud2}を使います。

install.packages("wordcloud2")
library(wordcloud2)

rres_freq %>% 
  filter(Info1=="名詞"|Info1=="形容詞") %>%
  select(Term,Freq) %>% 
  wordcloud2(shape="circle" ,#形を丸
             size=0.5,#サイズは0.5
             color = "random-dark")#色指定

ワードクラウド

出ました。ワードクラウドはこのように、出現頻度の多い単語が大きく表示されます。パッとみて"データ"、"サイエンティスト"、"分布"、"解析"などの単語が多いことがわかりますね。指定できる引数には様々なものがありますが、今回は形を丸、サイズは0.5、色は"random-dark"としてあります。

サイズを大きくしすぎると最頻値の単語が大きすぎて入りきらずに表示されないことがあるため注意してください。ちなみに形をハートにしたり、星にしたりもできて遊び心満載です笑

共起語、n-gram

頻度を調べたら、今度はどんな単語と一緒に使われているのか、単語同士の前後関係を調べることができれば、さらに深い解析ができそうです。これをn-gram、または共起語と呼びます。(厳密にはこの二つは意味が少し異なります。)共起語を調べるにはcollacate{RMeCab}を使います。こちらもファイル形式で渡す必要があるので、先ほどのtempを使いましょう。

res_collocate <- collocate(temp,node="データ",span=5)
>res_collocate %>% head()

          Term Before After Span Total
1           AI      0     1    1     4
2           AR      0     1    1     4
3 AirPassenger      1     0    1     1
4           GB      1     0    1     1
5          GUI      0     1    1     1

collacate{RMeCab}は調べたい単語と調べる前後関係の範囲を指定します。結果の見方は、5単語以内を範囲とすると、AIという単語は"データ"という単語の後に1回現れているという意味になります。しかし、出現頻度だけを共起語の判断基準として使うことについては議論があるようなので、頻度以外の指標としてT score(T),Mutual Information(MI)などを使うことがあります。それを算出するには、collScores{RMeCab}を使って、

> collScores(res_collacate,node="データ",span=5) %>% head()
          Term Before After Span Total         T       MI
1           AI      0     1    1     4 0.6320314 1.442345
2           AR      0     1    1     4 0.6320314 1.442345
3 AirPassenger      1     0    1     1 0.9080078 3.442345
4           GB      1     0    1     1 0.9080078 3.442345
5          GUI      0     1    1     1 0.9080078 3.442345
6           GW      0     1    1     2 0.8160157 2.442345

とします。詳しくは参考書をご覧ください。

共起ネットワーク

さて、先ほどは一単語のみを選んで、共起語を調べましたが、今度は全ての単語で共起語を調べてみましょう。NgramDF{RMeCab}を使います。 関数にはファイルを渡し、引数にはtypeで文字(0)、単語(1)、品詞(3)のどのタイプの共起語か、Nで何個の共起語か、posでどの品詞かを指定します。

ngram <- NgramDF(temp,
                 type = 1,#単語の共起語
                 N=2,#2単語を繋げる
                 pos=c("名詞","形容詞"))#デフォルトでこれになる

>ngram %>% 
  arrange(desc(Freq)) %>% 
  head()

  Ngram1           Ngram2 Freq
1   医療               職   49
2     時             系列   43
3 データ サイエンティスト   41
4     職           データ   37
5   機械             学習   30
6   因果             推論   17

共起語には"医療"と"職"が最頻で49回となっています。これをわかりやすく可視化してみましょう。パッケージは{igraph}を使います。{igraph}の詳しい使い方は以下がわかりやすいです。

Rとigraphを使ったネットワーク解析と可視化

やってみます。

par(mar=c(0.5,0.5,0.5,0.5))#余白を狭くする

ngram %>% 
  filter(Freq>=5) %>% #5回以上出現する共起語
  graph.data.frame(directed = F) %>% #おまじない
  plot(vertex.size=3, #ノードの大きさ
       vertex.label=V(.)$name, ##ノードのラベル
       vertex.label.font=1, #ラベルのフォント
      vertex.label.cex=1,#ラベルの大きさ
       vertex.frame.color="red", #ノードのいろ
       family="HiraKakuPro-W3",#日本語を表示させる
      vertex.label.dist=0)#ノードとラベルとの距離

共起ネットワーク

おお!単語や形容詞同士の繋がりがわかりやすくなりました。これで単語間の関係性を見ることができます。

こうやって自分のTweetを見るのは面白いですねー

まとめ

今回は統計学でいうところの記述統計、つまり簡単な集計をわかりやすくするためのテキストマイニング 手法、ワードクラウド、n-gram、共起ネットワークを紹介しました。テキストマイニングはとっつきにくそうで、以外に簡単にできてしまうので、是非とも入門として本記事を参考にしてみてください。

※本記事は筆者が個人的に学んだことをまとめた記事なります。所属する組織の意見・見解とは無関係です。また、数学の記法や詳細な理論、用語等で誤りがあった際はご指摘頂けると幸いです。

参考

以下の2冊は、簡単な集計から機械学習を用いた文章のクラス分類等まで、Rで行うことのできるテキストマイニング 手法が網羅されています。テキストマイニング を始めたいと思ったら、まず目を通してみることをお勧めします。

Rによるやさしいテキストマイニング

Rによるやさしいテキストマイニング

Rによるやさしいテキストマイニング [活用事例編]

Rによるやさしいテキストマイニング [活用事例編]

Rとigraphを使ったネットワーク解析と可視化

rtweetパッケージでTwitter APIからデータを取るのが超お手軽になってた - Technically, technophobic.