はじめに
3月、別れの季節ということでお世話になった方へ寄せ書きを渡すことがあります。
この記事では、ワードクラウドを使った一風変わったエンジニアらしい寄せ書きをつくる方法を紹介します。
完成形
寄せ書きのメッセージからワードクラウドを作成します。事前準備するイラストをマスク画像として使い、良い感じのデザインのものにします。
環境
- Google Colaboratory(Google Colab)
作成環境としては、Google Colabを利用して、Webブラウザ上で作業しました。
事前準備
事前準備としては、まずは寄せ書きのメッセージとワードクラウドの出力領域の形をデザインするためのマスク画像を用意します。
これらのファイルは、Google Colabから使うために、Googleドライブに保存します。
寄せ書きのメッセージ
各人からの寄せ書きのメッセージを、以下のようにテキスト形式のファイルにまとめます。
○○さん、定年退職おめでとうございます。
これからは大好きな趣味を存分に楽しんでください。
○○さん、在職中は色々とお世話になりました。
これからもお体を大切にいつまでもお元気で。
・・・
マスク画像
以下のイラストをベースにさせていただき、マスク画像を作成しました。
- https://publicdomainq.net/heart-envelope-love-letter-0055143/
- https://publicdomainq.net/flower-bouquet-0013857/
寄せ書きのワードクラウド作成
必要ライブラリインストール
!apt update
!apt install fonts-ipafont fonts-ipaexfont
!pip install mecab-python3 unidic-lite
mecab-python3のREADMEに従って、MeCab(形態素解析エンジン)のPythonライブラリと辞書、日本語フォントをインストールしました。
wordcloudとグラフ描画ライブラリのmatplotlibは既にインストールされていました。
インストールが完了したら、MeCabが使えることを次のコマンドで確認します。
import MeCab
print(MeCab.Tagger().parse("すもももももももものうち"))
]
0 秒
import MeCab
print(MeCab.Tagger().parse("すもももももももものうち"))
すもも スモモ スモモ 李 名詞-普通名詞-一般 0
も モ モ も 助詞-係助詞
もも モモ モモ 桃 名詞-普通名詞-一般 0
も モ モ も 助詞-係助詞
もも モモ モモ 桃 名詞-普通名詞-一般 0
の ノ ノ の 助詞-格助詞
うち ウチ ウチ 内 名詞-普通名詞-副詞可能 0
EOS
寄せ書きメッセージとマスク画像の読み込み
Googleドライブに保存した寄せ書きのメッセージとマスク画像を読み込みます。
実行すると、Googleドライブ利用の許可を求められるので、問題のない場合はアクセスを許可します。
from google.colab import drive
from PIL import Image
import numpy as np
# Googleドライブをマウント
drive.mount('/content/drive')
text = open('/content/drive/MyDrive/Colab/Yosegaki/messages.txt').read()
letter_mask = np.array(Image.open('/content/drive/MyDrive/Colab/Yosegaki/letter_mask.png'))
flower_mask = np.array(Image.open('/content/drive/MyDrive/Colab/Yosegaki/flower_mask.png'))
形態素解析
形態素解析の部分については、参考記事のコードを参考にさせていただきました。
引数に出力に含めない品詞の種類を指定可能なようにしています。
import MeCab as mc
def mecab_analysis(text, exclude_type=[]):
print("start mecab analysis")
t = mc.Tagger()
node = t.parseToNode(text)
output = []
while(node):
if node.surface != "":
word_type = node.feature.split(",")[0]
if len(exclude_type) != 0:
if word_type not in exclude_type:
output.append(node.surface)
else:
output.append(node.surface)
node = node.next
print("end mecab analysis")
return output
上記のメソッドを使って、寄せ書きのメッセージからワードクラウド作成に必要な単語のリストを出力します。
wordlist = mecab_analysis(text, exclude_type=["助詞", "接続詞"])
上の結果には、ひらがな1文字といったものも含まれるため、次の記事を参考にひらがな1文字は除外しました。
import re
re_hiragana = re.compile(r'^[あ-ん]$')
wordlist = list(filter(lambda s: not re_hiragana.fullmatch(s), wordlist))
ワードクラウド出力
以下がワードクラウドを出力する関数です。
stop_words
引数に出力に含めない単語を指定することができます。
import matplotlib.pyplot as plt
from wordcloud import WordCloud
def create_wordcloud(text, stop_words = []):
print("start create wordcloud")
# 環境に合わせてフォントのパスを指定する。
fpath = "/usr/share/fonts/truetype/fonts-japanese-mincho.ttf"
# 引数の詳細は、https://amueller.github.io/word_cloud/generated/wordcloud.WordCloud.html 参照
wordcloud = WordCloud(background_color="white",font_path=fpath, mask=flower_mask, colormap="spring", \
stopwords=set(stop_words), contour_width=1, contour_color='coral').generate(text)
print("end create wordcloud")
print("now showing")
plt.figure(figsize=(15,12))
plt.imshow(wordcloud)
plt.axis("off")
plt.show()
上記の関数を用いて、ワードクラウドを出力します。
ストップワードを調整して、良い感じになるようにします。
create_wordcloud(" ".join(wordlist), stop_words = [u'ます', u'です', u'ました', u'こと'])
ipynbファイル
参考までに、今回利用したipynbファイルを記載します。
──────────────────┐
│ ソースコードを表示(折りたたみ) │
└──────────────────┘
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "code",
"metadata": {
"id": "6oa_YJfWIaX_"
},
"source": [
"!apt update\n",
"!apt install fonts-ipafont fonts-ipaexfont\n",
"!pip install mecab-python3 unidic-lite"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"import MeCab\n",
"print(MeCab.Tagger().parse(\"すもももももももものうち\"))"
],
"metadata": {
"id": "Teefs-N4XkAT"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "Obsh0FhCKnrB"
},
"source": [
"from google.colab import drive\n",
"from PIL import Image\n",
"import numpy as np\n",
"# Googleドライブをマウント\n",
"drive.mount('/content/drive')\n",
"\n",
"text = open('/content/drive/MyDrive/Colab/Yosegaki/messages.txt').read()\n",
"letter_mask = np.array(Image.open('/content/drive/MyDrive/Colab/Yosegaki/letter_mask.png'))\n",
"flower_mask = np.array(Image.open('/content/drive/MyDrive/Colab/Yosegaki/flower_mask.png'))"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "-2DTt-djMUoJ"
},
"source": [
"print(text)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "9hO5znLtMBgD"
},
"source": [
"import MeCab as mc\n",
"\n",
"def mecab_analysis(text, exclude_type=[]):\n",
" print(\"start mecab analysis\")\n",
" t = mc.Tagger()\n",
" node = t.parseToNode(text)\n",
" output = []\n",
" while(node):\n",
" if node.surface != \"\":\n",
" word_type = node.feature.split(\",\")[0]\n",
" if len(exclude_type) != 0:\n",
" if word_type not in exclude_type:\n",
" output.append(node.surface)\n",
" else:\n",
" output.append(node.surface)\n",
" node = node.next\n",
"\n",
" print(\"end mecab analysis\")\n",
" return output"
],
"execution_count": 12,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "bL5-B8pKMJTJ"
},
"source": [
"wordlist = mecab_analysis(text, exclude_type=[\"助詞\", \"接続詞\"])\n",
"print(wordlist)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"import re\n",
"\n",
"re_hiragana = re.compile(r'^[あ-ん]$')\n",
"wordlist = list(filter(lambda s: not re_hiragana.fullmatch(s), wordlist))\n",
"print(wordlist)"
],
"metadata": {
"id": "G8ubrS0SiRVu"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "4sklSZeUM4E1"
},
"source": [
"import matplotlib.pyplot as plt\n",
"from wordcloud import WordCloud\n",
"\n",
"def create_wordcloud(text, stop_words = []):\n",
" print(\"start create wordcloud\")\n",
"\n",
" # 環境に合わせてフォントのパスを指定する。\n",
" fpath = \"/usr/share/fonts/truetype/fonts-japanese-mincho.ttf\"\n",
" # 引数の詳細は、https://amueller.github.io/word_cloud/generated/wordcloud.WordCloud.html 参照\n",
" wordcloud = WordCloud(background_color=\"white\",font_path=fpath, mask=flower_mask, colormap=\"spring\", \\\n",
" stopwords=set(stop_words), contour_width=1, contour_color='coral').generate(text)\n",
" print(\"end create wordcloud\")\n",
"\n",
" print(\"now showing\")\n",
" plt.figure(figsize=(15,12))\n",
" plt.imshow(wordcloud)\n",
" plt.axis(\"off\")\n",
" plt.show()"
],
"execution_count": 30,
"outputs": []
},
{
"cell_type": "code",
"source": [
"create_wordcloud(\" \".join(wordlist), stop_words = [u'ます', u'です', u'ました', u'こと'])"
],
"metadata": {
"id": "T-S2owPdb5DD"
},
"execution_count": null,
"outputs": []
}
]
}
参考