誰でもできるPythonでワードクラウド(word cloud)を作る方法(マスクも使えます)

2024/04/28

AI 開発試行

Pythonでワードクラウドを作る方法について、まとめてみました。

以下サイトを参考にさせていただいております。


ワードクラウドの基本

ワードクラウドとは

ワードクラウドは、文章のテーマや内容を視覚的に表すために、繰り返し使われる単語を大きく表示する表現方法です。文字データからよく使われる言葉を抜き出し、出現回数に応じて文字の大きさや色を変えて可視化します1。例えば、ウェブサイトの検索キーワードをワードクラウドにすると、どの言葉が多く使われているか一目で分かります。
ワードクラウドが内部でやっていることは以下の通りとなります。

  • 分析するテキストを、単語に分解します
  • 単語ごとにテキストに出現する回数をカウントします
  • 出現回数が高い順に単語を並び替えを行い、出現回数に応じて表示サイズを変えるプログラムを実行します

分析するテキストを作成するには

ワードクラウドは、英語圏のアプリケーションとなっています。空白で区切られた文字列を入力とします。日本語については品詞分解をする必要があります。今回は「Jannome」を利用します。「Mecab」というソフトもありますが何度か挑戦しましたが扱いが難しかったため切り替えました。

Janomenについてですが、Pythonの形態素解析エンジンで、日本語テキストを形態素ごとに分割し、品詞を判定したり分かち書き(単語に分割)したりできます。MeCabと同等の解析結果を提供し、簡単にインストールできるシンプルなAPIを備えています。バージョン4.0以降ではtokenize()メソッドがジェネレータを返すため、リストを取得する場合はlist()を使用します。

Pythonでの実装方法

GoogleColabo上でライブラリをインストールし、処理を実行していきます。

janome関係ライブラリをpipでインストール


  !pip install janome
  from janome.tokenizer import Tokenizer
  from janome.analyzer import Analyzer
  from janome.charfilter import *
  from janome.tokenfilter import *
  import re
  

入力データの準備


  import requests
  from bs4 import BeautifulSoup
  url = "https://www.aozora.gr.jp/cards/000148/files/789_14547.html"  # 青空文庫よりテキストを抽出
  response = requests.get(url)
  soup = BeautifulSoup(response.content, "html.parser")
  s = soup.get_text()
  

入力データの前処理

テキストデータを単語に分解し、名詞と動詞、形容詞だけを抽出します。クリーニングも実施します。


  # データ正規表現処理 上から順に処理される
  char_filters = [UnicodeNormalizeCharFilter(),
                  #Unicodeを正規化することで表記ゆれを吸収
                  RegexReplaceCharFilter('<.*?>', ''),
                  #html文書を想定してタグを削除する
                  RegexReplaceCharFilter('([ぁ-んー]+|[ァ-ンー]+|[\\u4e00-\\u9FFF]+|[ぁ-んァ-ンー\\u4e00-\\u9FFF]+)(\n)([ぁ-んー]+|[ァ-ンー]+|[\\u4e00-\\u9FFF]+|[ぁ-んァ-ンー\\u4e00-\\u9FFF]+)', r'\1\3'),
                  #改行前後の文字が日本語文字の場合は改行を削除する。それ以外はスペースに変換する。
                  RegexReplaceCharFilter('\n', ' '),
                  RegexReplaceCharFilter('\t', ' '),
                  # 残った改行とタブ記号はスペースに置換する
                  ]

  # データ前処理 上から順に処理される
  token_filters = [
                   LowerCaseFilter(), #英字を小文字にする
                   CompoundNounFilter(),# 複合名詞を作成する
                  ]

  # 形態要素分析の実施
  a = Analyzer(char_filters=char_filters, token_filters=token_filters)
  results = a.analyze(s)

  # 分析結果を空白(スペース)を区切りとした品詞の文字列にする
  sent = ""
  for token in results:
      if token.extra is None : # 品詞名がつけられない文字は対象外
          sent = sent
      else:
          if token.extra[0].split(',')[0] in ['名詞']: # tokenの1列目に品詞名がある"名詞"を抽出対象とする
              sent += token.surface + " " # 表層形を抽出

  # results確認用
  print(sent)
  
抽出結果としては以下の通りになります。
  
 夏目漱石 吾輩 猫 吾輩 猫 夏目漱石 一 吾輩 猫 名前 どこ 見当 何 所 いた事 記憶 吾輩 ここ 人間 もの あと それ 書生 人間中...
  

ワードクラウドの作成

前節で作成した入力データを元にワードクラウドを作成します。ワードクラウドでは日本語fontが用意されていませんので、IPAのサイトttfファイルをダウンロードを事前にしておきます。またワードクラウドを画像でマスクする場合は白黒の画像を事前に用意します。IPAについては検索すると事例がいくつかできますが、マスク画像は無料で使える画像を見つけてくるのが大変なので、作業手順を最後にまとめます。

ワードクラウドの作成


  # wordcloudを実行
  from wordcloud import WordCloud
  import matplotlib.pyplot as plt
  %matplotlib inline
  from PIL import Image
  import numpy as np

  # 画像読み込み
  mask = np.array(Image.open("kuma.png"))

  # フォントを設定(content配下)
  fpath = "ipagp.ttf"

  # colormapリスト
  color_map_list=[
      'inferno', 'magma', 'plasma', 'viridis',
      'Blues', 'BuGn', 'BuPu', 'GnBu',
      'Greens', 'Greys', 'OrRd', 'Oranges',
      'PuBu', 'PuBuGn', 'PuRd', 'Purples',
      'RdPu', 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd',
      'binary', 'gist_yarg', 'gist_gray', 'gray',
      'bone', 'pink', 'spring', 'summer',
      'autumn', 'winter', 'cool', 'Wistia',
      'hot', 'afmhot', 'gist_heat', 'copper',
      'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu', 'RdYlBu',
      'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic',
      'Pastel1', 'Pastel2', 'Paired', 'Accent', 'Dark2',
      'Set1', 'Set2', 'Set3', 'tab10', 'tab20', 'tab20b', 'tab20c',
      'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern', 'gnuplot',
      'gnuplot2', 'CMRmap', 'cubehelix', 'brg', 'hsv', 'gist_rainbow', 'rainbow',
      'jet', 'nipy_spectral', 'gist_ncar']

  # 不要な単語を設定
 stop_word_list = ["もの","そう","よう","ここ","これ","それ","の","ん","事","する", "しまっ", "し", "さ", "ある", "あっ","い","ため","こと","れ","いる","なっ"]

  # wordcloud処理
  wc = WordCloud(
      background_color="white", # 背景
      width=900, # 図の大きさ
      height=900,
      font_path=fpath, # フォントの設定
      colormap=color_map_list[color_map_list.index("coolwarm")],  # 文字色の選択
      mask=mask, # 図の枠,
      contour_width=1, # 図の枠線の太さ
      contour_color="steelblue", # 図の枠線の色
      stopwords=stop_word_list, # 不要文字
      max_words=50, # 最大文字数
      ).generate(sent)

  # imgの表示
  plt.figure(figsize=(5,5))
  plt.axis("off")
  plt.imshow(wc, interpolation="bilinear")
  

抽出結果としては以下の通りになります。


マスク画像の作成

OffcieやBing検索等で、無料の白黒アイコンを検索することができます。大概は背景が透過したpngファイルであるため、その背景を白塗りつぶすことで、マスク用の画像ができあがりです。


まとめ

非常に簡単に作成できますね。これで一味違ったWebサイトができそうです。