【自然言語処理】形態素解析で品詞毎に頻出ワードを抽出

こんにちは。今回は、テキストデータ分析の切り口の1つとして、品詞毎の頻出ワードの特定を試してみましたので、その方法をまとめておこうと思います。分析対象データには、ツイッター上の「新型コロナウィルス」を含むツイートデータを使いました*。(データの深掘り分析は別の記事に分けてやりたいと思います。本記事では、やり方にフォーカスを当てて解説してまいります)

*2020年4月8日の11:00-12:00の1時間ほどのツイートのうち、18000ツイートを抽出

それでは、早速進めてまいります。

以下では、日本語の形態素解析ライブラリである、MeCabを利用しておりますので、MeCabを使える前提でお話を進めてまいります。

形態素解析で品詞情報と合わせて結果を取得する方法

これには、MeCabのParseToNode()メソッドを利用します。

ParseToNodeメソッドがどのような情報を返すのかを理解するために、実際にコードを書いてみます。サンプルのテキストは、ツイッターから取得したランダムなツイートデータを利用させていただいています。

import MeCab

## 分析用テキストのサンプル
text = "今、参議院内の幹事長室で予算委員会を見ています。野党の質問が始まって40分経過しましたが、\n先刻武漢からの飛行機が到着し、目の前に総理や厚労大臣等、新型コロナウイルス感染症に対応している責任者が列席している。\nこのシチュエーションで感染症について質問をしない感覚に驚いています。"

tagger = MeCab.Tagger('-Owakati -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')

## ParseToNode
node = tagger.parseToNode(text)

## ご参考:Parse
#node = tagger.parse(text)

はじめに、ご参考ですが、parseToNodeメソッドではなくparseメソッドを利用すると、以下のように分かち書きされたテキスト文が取得されます。

今 、 参議院 内 の 幹事長 室 で 予算委員会 を 見 て い ます 。 野党 の 質問 が 始まっ て 40分 経過 し まし た が 、 先刻 武漢 から の 飛行機 が 到着 し 、 目 の 前 に 総理 や 厚 労 大臣 等 、 新型コロナウイルス感染症 に 対応 し て いる 責任者 が 列席 し て いる 。 この シチュエーション で 感染 症 について 質問 を し ない 感覚 に 驚い て い ます 。 \n

本題のParseToNodeメソッドを利用した場合ですが、以下のような情報が帰ってきます。

while node:
    print(node.surface+" : "+node.feature)
    node = node.next
## 実行結果
 : BOS/EOS,*,*,*,*,*,*,*,*
今 : 名詞,副詞可能,*,*,*,*,今,イマ,イマ
、 : 記号,読点,*,*,*,*,、,、,、
参議院 : 名詞,固有名詞,組織,*,*,*,参議院,サンギイン,サンギイン
内 : 名詞,接尾,一般,*,*,*,内,ナイ,ナイ
の : 助詞,連体化,*,*,*,*,の,ノ,ノ
幹事長 : 名詞,固有名詞,一般,*,*,*,幹事長,カンジチョウ,カンジチョー
室 : 名詞,接尾,一般,*,*,*,室,シツ,シツ
で : 助詞,格助詞,一般,*,*,*,で,デ,デ
予算委員会 : 名詞,固有名詞,一般,*,*,*,予算委員会,ヨサンイインカイ,ヨサンイーンカイ
を : 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
見 : 動詞,自立,*,*,一段,連用形,見る,ミ,ミ
て : 助詞,接続助詞,*,*,*,*,て,テ,テ
い : 動詞,非自立,*,*,一段,連用形,いる,イ,イ
ます : 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。 : 記号,句点,*,*,*,*,。,。,。

説明ですが、ParseToNode()メソッドが返すのは、Nodeオブジェクトになりますが、このオブジェクトには以下の2つのプロパティがあります。

  • feature:分解された単語を含みます。
  • surface:分解された単語の「品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音」情報を含みます。

ですので、これを利用すれば、特定品詞に絞って単語のリストを作成することができます。

品詞ごとに頻出ワードを抽出

それでは、先ほどの方法を活用して、品詞毎に頻出ワードの抽出を行ってみたいと思います。

前処理(データ絞り込み+形態素解析+品詞毎の単語リスト抽出)

まず、ツイッターデータ特有ではありますが、ツイートにはリツイート機能がありますので、リツイートされたツイートを全て個別にカウントしていては、おそらくそのツイートに含まれる単語が頻出ワードとして上位に上がってくることが想定されます。ですので、リツイートによるツイートは事前に除外しておいたほうが良さそうです。

df_tweet = df_tweet[df_tweet["retweeted_status"].isna()].reset_index(drop=True)

続けて、形態素解析+品詞抽出処理です。以下がテキストのパース関数です。

def textParser_class(text, category):

    ## 分かち書きのみ
    tagger = MeCab.Tagger('-Owakati -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')

    ## 品詞毎に取得
    word_count = 0
    sentense = ""
    
    node = tagger.pa
rseToNode(text)
    
    while node:
    #    print(node.surface+" : "+node.feature)
        if node.feature.split(",")[0] == category:
            sentense += " "+node.surface
        else:pass

        node = node.next
    
    return sentense

以下、上記のパーサーを使って品詞抽出を行うです。(もっとうまい書き方がある気がします・・ご教示ください・・)

#df_tweetは、Twitter APIで取得したデータをデータフレーム化したもの。

## テキスト前処理(詳細は割愛しますが、preProcessor関数で、記号や数字の除去、単語の正規化等を行っておきます)
df_tweet["text_前処理後"] = df_tweet["text"].apply(lambda x: preProcessor(x))

## 特定品詞のみを抽出
df_tweet["text_形態素解析後_名詞"] = df_tweet["text_前処理後"].apply(lambda x: textParser_class(x,"名詞"))
df_tweet["text_形態素解析後_動詞"] = df_tweet["text_前処理後"].apply(lambda x: textParser_class(x,"動詞"))
df_tweet["text_形態素解析後_形容詞"] = df_tweet["text_前処理後"].apply(lambda x: textParser_class(x,"形容詞"))

## それぞれ1つのテキスト文にする
text_meishi = ""
text_doushi = ""
text_keiyou = ""
for i in range(len(df_tweet)):
    text_meishi += df_tweet["text_形態素解析後_名詞"][i]
    text_doushi += df_tweet["text_形態素解析後_動詞"][i]
    text_keiyou += df_tweet["text_形態素解析後_形容詞"][i]

以上で、形態素解析した結果から、特定品詞のみの単語リストの抽出が完了しました。次からは、この単語リストを使って、頻出ワードの特定を行っていきます。

Word Cloudで可視化

まずはWordCloudで品詞毎に頻出単語を可視化してみます。”頻出”の数え方ですが、WordCloudライブラリのデフォルトはBag-Of-Wordsベースなのかな?TF-IDFベースのWordCloudを出すこともできるようです。が、それはまたの機会に。

import WordCloud

def GenerateWordCloud(target_text):
    wordcloud = WordCloud(background_color="white",font_path='ipag.ttf',
        stopwords = set(stop_words),
        collocations = False, # 複合語のオプションをオフ
        width=800,height=600).generate(target_text)

    plt.figure(figsize=(24,10))
    plt.imshow(wordcloud)
    plt.show()
    
GenerateWordCloud(text_meishi)
GenerateWordCloud(text_doushi)
GenerateWordCloud(text_keiyou)

名詞

動詞

形容詞

できました!名詞や、形容詞についてはもう少し丁寧な分析をすることで色々な示唆が見えてきそうです。動詞は、どうなんでしょう?今回の場合だと、名詞や形容詞に絞って分析をしても良いのではと思いました。

Bag-Of-Words / TF-IDFベースで単語の出現頻度・特徴語を算出

上のライブラリでよしなにBag-Of-Words?ベースで頻出度を計算してくれていましたが、自分で実装するとこんな感じでしょうか。

Bag-Of-Words

from sklearn.feature_extraction.text import CountVectorizer

def Vectorization_BOW(df):
    vectorizer = CountVectorizer(token_pattern=u'(?u)\\b\\w+\\b',max_features=50,stop_words=stop_words)
    vecs = vectorizer.fit_transform(df)
    header = vectorizer.get_feature_names()
    return vecs, header

vecs, header = Vectorization_BOW(df_tweet["text_形態素解析後_名詞"])
df_result = pd.DataFrame(vecs.toarray(), columns=header)
df_summarized = df_result.fillna(0).sum(axis=0)
df_summarized = df_summarized.sort_values(ascending=False)

名詞の場合だけですが、以下のような結果が得られました。

	出現回数
感染	427
感染拡大	325
対策	237
緊急事態	228
宣言	224
月日	214
お知らせ	185
影響	185
防止	180
ニュース	167
対応	149
日本	139
自粛	123
感染者	110
拡大	104

TF-IDF

def Vectorization_TFIDF(df):
    vectorizer = TfidfVectorizer(use_idf=True, token_pattern=u'(?u)\\b\\w+\\b',max_features=100000,stop_words=stop_words)
    vecs = vectorizer.fit_transform(df)
    header = vectorizer.get_feature_names()
    return vecs, header

vecs, header = Vectorization_TFIDF(df_tweet["text_形態素解析後_名詞"])
df_result = pd.DataFrame(vecs.toarray(), columns=header)
df_summarized = df_result.fillna(0).mean(axis=0)
df_summarized = df_summarized.sort_values(ascending=False)
df_summarized.head(15)

同じく、以下の結果が得られました。

感染      0.027389
感染拡大    0.020502
対策      0.017890
緊急事態    0.016760
宣言      0.016496
ニュース    0.015491
影響      0.014867
月日      0.014487
お知らせ    0.014258
対応      0.013800
防止      0.012933
日本      0.011812
確認      0.010585
自粛      0.010116
感染者     0.009810

今回はあまり大きな違いは見られませんでした。まあ、名詞に絞っているので、当然といえば当然なのかもしれません。

以上、今回はテキストデータに含まれる頻出・重要単語の特定を行って見る部分までの流れを解説いたしました。自然言語処理の分析の切り口の武器を色々と増やしたいと思っているので、次回以降、ポジ/ネガ分析、共起ネットワークの可視化などをできるように勉強を進めていきたいと思います。

本日も最後までご覧いただき、ありがとうございました!

0

この記事を気に入っていただけたらシェアをお願いします!

コメントを残す

メールアドレスが公開されることはありません。

ABOUT US

アバター
Yuu113
初めまして。Yuu113と申します。 兵庫県出身、東京でシステムエンジニアをしております。現在は主にデータ分析、機械学習を活用してビジネスモデリングに取り組んでいます。日々学んだことや経験したことを整理していきたいと思い、ブログを始めました。旅行、カメラ、IT技術、江戸文化が大好きですので、これらについても記事にしていきたいと思っています。