PythonのWordCloudで「こころ」の頻出単語を可視化する【形態素解析, 自然言語処理】

105, 2020-11-09

目次

Pythonによる頻出単語の可視化

ワードクラウド」というのは文章の中の頻出単語を可視化した画像のことです。
自然言語処理の分野でよく使われます。
文章の中の名詞や動詞が、どれがよく使われているのかと言うのを視覚的に非常にわかりやすく表示することが可能です。

Pythonにはこのワードクラウドを簡単に表示するためのライブラリがあります。
その名も「WordCloud」です。
WordCloudに例えば名詞が羅列されたテキストを渡すと、WordCloudはそのテキストを解析してワードクラウドの画像を生成してくれます。
今回はこのWordCloudを使って、簡単なスクリプトを作成しました。
show-wordcloud.py」というスクリプトです。

この記事ではこのshow-wordcloud.pyの紹介と解説を行います。
具体的には↓の内容になります。

  • show-wordcloud.pyの全コード

  • Janomeによる形態素解析

  • WordCloudによる画像の生成

  • matplotlibで画像を表示

  • show-wordcloud.pyで「こころ」を解析

show-wordcloud.pyの全コード

最初に作成した「show-wordcloud.py」のコードの全文を紹介します。

"""
    show-wordcloud.py

    標準入力から文字列を読み込み、名詞のみを抽出してワードクラウドを表示する

    Usage:

        python show-wordcloud.py
        or
        curl https://xxx.xxx | python show-wordcloud.py
"""
from janome.analyzer import Analyzer
from janome.tokenfilter import POSKeepFilter
from wordcloud import WordCloud
import matplotlib.pyplot as plt
from bs4 import BeautifulSoup
import sys
import io


def analyze(src):
    """
    srcを解析して名詞のみが羅列されたテキストに変換する

    @param {str} src
    @return {str}
    """
    # HTMLからテキストのみを抽出
    soup = BeautifulSoup(src, 'html.parser')
    src = soup.get_text()

    # janomeのフィルター
    # 名詞のみを抽出するのでPOSKeepFilterに名詞を指定
    token_filters = [POSKeepFilter(['名詞'])]

    # token_filtersを指定してAnalyzerを生成
    an = Analyzer(token_filters=token_filters)

    # 解析してトークン列(名詞の列)に
    toks = an.analyze(src)

    # トークン列を半角スペース区切りのテキストに変換
    text = ' '.join([tok.surface for tok in toks])

    return text


def show_wordcloud(text):
    """
    textからワードクラウドを表示する

    @param {str} text
    """
    # WordCloudで使うフォント。ここではWindowsのフォントを使用
    font_path = 'C:\\Windows\\Fonts\\msgothic.ttc'

    # WordCloudをオブジェクトに
    wordcloud = WordCloud(
        background_color='white',  # 背景色
        font_path=font_path,  # フォントのパス
        width=300,  # 横幅
        height=200,  # 高さ
    )

    # textを元に画像を生成
    wordcloud.generate(text)

    # matplotlibで生成した画像を表示する
    plt.figure(figsize=(8, 4))  # figsize=(横幅, 高さ)
    plt.imshow(wordcloud)
    plt.axis('off')
    plt.show()  # 表示


def main():
    sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='cp932')
    src = sys.stdin.read()
    text = analyze(src)
    show_wordcloud(text)


main()

スクリプトの使い方

↑のコードを「show-wordcloud.py」などのファイルに保存します。
環境にpipで↓のパッケージをインストールします。

pip install janome matplotlib wordcloud BeautifulSoup4

コマンドプロンプトなどのシェルからスクリプトを↓のように実行します。

python show-wordcloud.py

デフォルトでは標準入力から入力を読み取りますので何か入力し、Ctrl+ZCtrl+Dなどを入力すると解析が始まります。
解析が完了すると画面にワードクラウドの画像を表示します。

また、Curlなどと組み合わせる場合は↓のようにパイプを使います。

curl https://xxx.xxx | python show-wordcloud.py

このスクリプトは標準入力がデフォルトでcp932になっています(青空文庫がcp932のため)。
そのためUTF-8のコンテンツを読み込ませたい場合は、main関数内の↓の部分、

    sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='cp932')

encoding='cp932'のところをencoding='utf-8'などに変更してください。
(スクリプトの簡便さのためにオプションによる切り替えは省略しています)

Janomeによる形態素解析

まず、WordCloudに文字列を解析させたいわけですが、そのためには単語が羅列されたテキストを作る必要があります。
日本語の文章を単語のリストに変換するには形態素解析という技術を使います。
形態素解析を行えるライブラリはMecabなどが有名ですが、PythonにはJanomeというライブラリもあります。
Janomeはpipで簡単にインストールできるので、このスクリプトではJanomeを使ってコードを書いています。

Janomeにはトーカナイザー(janome.tokenizer)という字句解析を行うモジュールがあり、これが基本となるモジュールです。
今回はこれは使っていません。
トーカナイザーの使い方については↓の記事をご覧ください。

今回はJanomeのアナライザー(janome.analyzer)という応用的な使い方をするモジュールを使います。
このアナライザーは品詞のフィルタリングなどを簡単に行えるモジュールです。
スクリプトでは名詞の単語を抽出したいわけなので、アナライザーはまさにうってつけという訳です。

スクリプトのコードを見てみましょう。
analyze()と言う関数でJanomeを使った形態素解析を行っています。
この関数は引数として日本語の文章の文字列を取り、結果を名詞が羅列されたテキストとして返します。

def main():
    ...
    text = analyze(src)
    ...

analyze()関数内ではJanomeのアナライザーを使った形態素解析を行っています。
最初に引数srcがHTMLであった場合にそなえて、BeautifulSoup4というHTMLパーサーでsrcをパースしています。

    # HTMLからテキストのみを抽出
    soup = BeautifulSoup(src, 'html.parser')
    src = soup.get_text()

↑のようにBeautifulSoupのオブジェクトのメソッドget_text()を使うと、タグを取り除いたテキストを取得することが出来ます。
BeautifulSoupを使うにはbs4モジュールからBeautifulSoupクラスをインポートする必要があります。

from bs4 import BeautifulSoup

JanomeのAnalyzerを使うにはjanome.analyzerモジュールからAnalyzerクラスをインポートします。
それからフィルターとしてjanome.tokenfilterモジュールからPOSKeepFilterクラスをインポートします。
POSKeepFilterはアナライザーで解析するときに特定の品詞のみを抽出するフィルターです。

from janome.analyzer import Analyzer
from janome.tokenfilter import POSKeepFilter

↓のようにPOSKeepFilterに抽出したい品詞のリストを渡してオブジェクトにし、token_filtersというリストにします。

    token_filters = [POSKeepFilter(['名詞'])]

それからこのtoken_filtersAnalyzertoken_filtersに指定して、Analyzerをオブジェクトにします。

    an = Analyzer(token_filters=token_filters)

生成したアナライザー(an)のメソッドanalyze()に文字列を渡すと解析が実行され、形態素解析が行われます。
その結果はトークン列で返ってきます。これは名詞のみのリストです。

    toks = an.analyze(src)

トークン列内のトークンはsurfaceという単語の表層形を表す属性を持っています。
表層形とは単語の元の文章そのままの表記です。
このsurfaceを参照し、↓のようにリスト内包表記と文字列のjoin()を使って、名詞が羅列されたテキストに変換します。

    text = ' '.join([tok.surface for tok in toks])

変換したテキストを、analyze()の最後でreturnしてanalyze()関数の仕事は終わりです。

WordCloudによる画像の生成

analyze()で日本語の文章を解析したら次はWordCloudによる画像の表示です。
これはshow_wordcloud()関数で行います。

def main():
    ...
    show_wordcloud(text)

show_wordcloud()関数はテキストを引数に取ります。
この引数にはanalyze()の結果のテキストを渡します。

WordCloudは画像で文字列を生成していますが、この画像による文字列にはフォントが必要です。
そのため外部からフォントを仕入れてそのパスを指定する必要があります。

    font_path = 'C:\\Windows\\Fonts\\msgothic.ttc'

今回はWindows10に最初から入っているmsgothic.ttcフォントを使っています。

次にWordCloudをオブジェクトにします。これはWordCloudクラスを使います。
WrodCloudクラスを使うにはwordcloudモジュールからWordCloudクラスをインポートする必要があります。

from wordcloud import WordCloud

WordCloudをオブジェクトにする時にさきほどのフォントのパス、それから背景色なども指定します。

    # WordCloudをオブジェクトに
    wordcloud = WordCloud(
        background_color='white',  # 背景色
        font_path=font_path,  # フォントのパス
        width=300,  # 横幅
        height=200,  # 高さ
    )

WordCloudをオブジェクトにしたら、そのメソッドであるgenerate()にテキストを渡して画像を生成します。

    wordcloud.generate(text)

これでワードクラウドの画像が生成されました。

matplotlibで画像を表示

次にこの画像を表示しますが、これにはmatplotlibというライブラリを使います。
matplotlibを使うには↓のようにpltをインポートする必要があります。

import matplotlib.pyplot as plt

matplotlibにさきほど生成したwordcloudオブジェクトを指定して画面に画像を表示します。

    # matplotlibで生成した画像を表示する
    plt.figure(figsize=(8, 4))  # figsize=(横幅, 高さ)
    plt.imshow(wordcloud)
    plt.axis('off')
    plt.show()  # 表示

show-wordcloud.pyで「こころ」を解析

ではこのスクリプトを使って青空文庫に掲載されている夏目漱石の「こころ」を解析してみましょう。
↓のようにコマンドを打って実行します。

curl 青空文庫のURLをここに書く | python show-wordcloud.py

しばらくすると↓のような画像が表示されます。

【0105】out1.png

画像を見ると、やはり主人公だけあって「先生」というワードが多いのが視覚的にわかります。
それから「よう」、「もの」、「それ」も多いですね。

おわりに

PythonのWordCloudを使うと簡単に頻出単語を視覚化することが出来ました。
このスクリプトをあなたのツールに加えてみてはいかがでしょうか?
ライセンスはMITです。改造もご自由にどうぞ。

(^ _ ^)

雲のような人間になりたい



この記事のアンケートを送信する