ホーム
記事一覧
プライバシーポリシー
免責事項
お問い合わせ

前処理を行いツイートをWordCloudで可視化する方法

2020-03-31

本記事では、Twitter APIで集めたツイートに前処理を行い、WordCloudで可視化する方法を紹介します。

最終的にこんな感じになります。

Twitter APIやツイート収集システムについては以下の記事で紹介しました。

前処理概要

日常用いられる文章は実は様々な形をしていて、そのままではプログラムに読み込ませて解析をするのは難しいです。

そこで、自然言語処理では解析に入る前にテキストを解析に適した状態にする前処理が必要になります。

今回行う具体的な前処理の中身は以下の通りです。

  • 不要情報の除去(記号・URLなど)
  • 正規化(大文字小文字変換、半角全角統一、数字を0になど)
  • 形態素解析(単語分割、品詞指定)
  • ストップワードの除去

おそらくもっと正確にやるなら同義語辞書による変換も必要になるでしょう。

ユーザー辞書登録については以前紹介した記事で行っているので、形態素解析で反映されてます。

ツイートデータを前処理

Twitter APIで収集したツイートに前処理を行います。

実行環境は以下の記事にあるようにDockerで行い、コードはJupyter NoteBookに書いていきます。

まずはpandasでツイートを保存したcsvを読み込みます。

import os
import pandas as pd
import numpy as np
import emoji
import spacy
import re
import neologdn
import json
from wordcloud import WordCloud
from collections import Counter

path = "<file path>"
file_name = "<file name>.csv"

df = pd.read_csv(os.path.join(path,file_name))

# 必要な列を定義。textがツイート、user_mentionsはツイートに含まれるメンション
column = ["text", "user_mentions"]

次にツイートに含まれるメンションを除きます。メンションはAPIの結果にツイート本文とは別に抽出できるようになっているので、csv作成時にあらかじめ列にいれておきました。

bool_list = df["user_mentions"].isna()

for idx, bol in enumerate(bool_list):
    if bol:
        continue
    else:    
        mention_list = df["user_mentions"].copy().loc[idx].split(",")
        for mention in mention_list:
            df["text"].loc[idx] = df["text"].copy().loc[idx].replace("@"+mention, '')                   

python的にあまりよくない書き方かもしれないですが、とりあえずこれでメンション部分をツイートから除外できます。

さて、いよいよ前処理部分です。(メンション除外も前処理っぽいですが、、)

def preprocess_wordcloud(doc):
    
    # 絵文字削除
    doc = ''.join(['' if c in emoji.UNICODE_EMOJI else c for c in doc])
    print("絵文字削除")
    
    # 不要記号削除
    pattern = '[!"#$%&\'\\\\()*+,-./:;<=>?@[\\]^_`{|}~「」〔〕“”◇ᴗ●↓→♪★⊂⊃※△□◎〈〉『』【】&*・()$#@。、?!`+¥%]'
    doc =  re.sub(pattern, ' ', doc)
    print("不要記号削除")
    
    doc = neologdn.normalize(doc)
    print("正規化")
    
    # 大文字・小文字変換
    doc = doc.lower()
    print("大文字小文字変換")
    
    # 数字を0に
    doc = re.sub(r'\d+', '0', doc)
    print("数字をゼロに")
    
    # 形態素解析
    print("形態素解析開始")
    nlp = spacy.load('ja_ginza')
    doc = nlp(doc)
    x = []
    for sent in doc.sents:
        for token in sent:
            if token.pos_ in ["PROPN","NOUN"]:
                x.append(token.lemma_)
                
    print("形態素解析完了")
    
    with open("<stopword file path>.txt", "r", encoding="utf-8") as f:
        stopwords = [word.replace('\n', '') for word in f.readlines()]
        
    x = [c for c in x if c not in stopwords]
    print("ストップワード除去")
    print(len(x))
    return x

text = preprocess_wordcloud(doc)    

形態素解析の結果のうち、固有名詞・名詞だけを抽出するようにしてます。指定するPOSタグについてはこちらの記事が見やすいです。

実行結果は以下のようになります。

前処理結果

自分のコードの書き方だと形態素解析が思ったより時間がかかります。といっても数分程度です。ただメモリ8GBの古いPCだと処理が終わらなかったです。

WordCloudの作成

続いては前処理済みのデータでWordCloudを作成します。

# リストをスペース区切りの分かち書きに
text_list = " ".join(text)

# 検索ワードは多すぎるので除外
text_list = text_list.replace("ブログ","")
text_list = text_list.replace("初心者","")

# WordCloud定義
wordcloud = WordCloud(width=600, height=400,font_path="/root/.fonts/NotoSansCJKjp-Regular.otf",background_color="black",collocations = False)

# テキストからワードクラウドを生成する。
wc = wordcloud.generate(text_list)

#画像ファイルとして保存
wc.to_file('wordcloud-ブログ-初心者.png')

これでWordCloudが生成できます。collocations=Falseとすることで複合語を表示しないようにできます。

結果は以下です。ちなみにデータはTwitter APIで「ブログ 初心者」と検索して得られた結果です。

wordcloud ブログ初心者

本記事の最初でツイートにのせたものはツイートの動詞や形容詞なども含まれており、さらに複合語もありにしていたのでやや見づらいです。

名詞・固有名詞と複合語をなしにするとシンプルで見やすいです。

WOrdCloudの結果については、「記事」はわかるとしても「収益」がこんなデカさになるのは面白いですね。みんな収益目当てでやっていると推測できます。

ハマったところ

ハマったところは以下です。

  • GiNZAで使われているSudachiPYのユーザー辞書登録
  • WordCloudの文字化け回避

1つ目については、Dockerで環境を作成したのですが、どこのパスに必要なsudach.jsonなどがあるのか混乱しました。また、GiNZAで使われているものとインストールされたSudachiPyの方にも同じようなファイルがあるので、どちらが正しいのかもわからなかったです。

結局、公式のドキュメントをしっかり読んだら解決できました。

2つめのWordCloudの文字化けは、フォントパスを指定しないと日本語が文字化けします。 これは情報がネットにたくさんあったのでそこまではまらなかったです。どちらかというと、日本語フォントをダウンロードして設定する工程を自動化するのに時間がかかりました。

ここらへんのハマりポイントも前回の記事の環境構築で回避できているはずです。

まとめ

本記事ではGiNZAを使ったツイートの前処理について書きました。

かなり基本的な前処理しかしていませんが、単語を眺めるには十分でした。

GiNZAはもっと高度なことが可能で他の機能も使ってさらに有意義な解析も行ってみたいです。

以下の記事がGiNZAの使い方についてかなり詳しく書いてあります。

参考書籍