今回も Word Cloud の話です。
前回は見た目の設定を変える話でしたが、今回は読み込ませるデータの話になります。
さて、Word Cloudを作るとき、
generate (もしくは generate_from_text) 関数に、 テキストを渡し、その中の出現回数でサイズを決めました。
しかし実際には、出現回数ではなくもっと別の割合でサイズを調整したいことがあります。
例えば、TF-IDFで重みをつけたい場合とか、トピックモデルのトピック別出現確率のようなもともと割合で与えられたデータを使いたい場合などです。
このような時は “単語: 頻度” の辞書(dict)を作成し、
generate_from_frequencies (もしくは fit_words) に渡すと実行できます。
ドキュメントの API Reference には詳しい説明がないので、ギャラリーの Using frequency をみる方がおすすめです。
今回はサンプルとして、ライブドアニュースコーパスから適当に1記事選んで、通常の単語の出現回数(今までと同じ方法)と、
TF-IDFで重み付けした方法(generate_from_frequenciesを使う)でそれぞれ WordCloudを作ってみました。
今まで、単語を名詞動詞形容詞に絞ったり平仮名だけの単語は外したりしていましたが、
今回は差が分かりやすくなるようにするためにSTOPWORDなしで全単語を含めています。(コード中で該当処理をコメントアウトしました。)
「てにをは」系の頻出語が小さくなってSTOPWORD無しでも分かりやすくなる効果が出ているのが感じられると思います。
import re
import MeCab
import pandas as pd
import unicodedata
import matplotlib.pyplot as plt
from wordcloud import WordCloud
from sklearn.feature_extraction.text import TfidfVectorizer
# 分かち書きの中で使うオブジェクト生成
tagger = MeCab.Tagger("-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd")
# ひらがなのみの文字列にマッチする正規表現
kana_re = re.compile("^[ぁ-ゖ]+$")
def mecab_tokenizer(text):
# ユニコード正規化
text = unicodedata.normalize("NFKC", text)
# 分かち書き
parsed_lines = tagger.parse(text).split("\n")[:-2]
surfaces = [l.split('\t')[0] for l in parsed_lines]
features = [l.split('\t')[1] for l in parsed_lines]
# 原型を取得
bases = [f.split(',')[6] for f in features]
# 品詞を取得
# pos = [f.split(',')[0] for f in features]
# 各単語を原型に変換する
token_list = [b if b != '*' else s for s, b in zip(surfaces, bases)]
# 名詞,動詞,形容詞のみに絞り込み
# target_pos = ["名詞", "動詞", "形容詞"]
# token_list = [t for t, p in zip(token_list, pos) if (p in target_pos)]
# ひらがなのみの単語を除く
# token_list = [t for t in token_list if not kana_re.match(t)]
# アルファベットを小文字に統一
token_list = [t.lower() for t in token_list]
# 半角スペースを挟んで結合する。
result = " ".join(token_list)
# 念のためもう一度ユニコード正規化
result = unicodedata.normalize("NFKC", result)
return result
# データ読み込み
df = pd.read_csv("./livedoor_news_corpus.csv")
# 形態素解析(全データ)
df["token"] = df.text.apply(mecab_tokenizer)
# サンプルとして用いるテキストを一つ選び、形態素解析する
text = df.iloc[1010].text
tokenized_text = mecab_tokenizer(text)
# tfidfモデルの作成と学習
tfidf_model = TfidfVectorizer(token_pattern='(?u)\\b\\w+\\b', norm=None)
tfidf_model.fit(df.token)
# 対象テキストをtf-idfデータに変換
tfidf_vec = tfidf_model.transform([tokenized_text]).toarray()[0]
# 単語: tf-idfの辞書にする。
tfidf_dict = dict(zip(tfidf_model.get_feature_names(), tfidf_vec))
# 値が正のkeyだけ残す
tfidf_dict = {k: v for k, v in tfidf_dict.items() if v > 0}
# 単語の出現頻度でWord Cloud作成
wc_0 = WordCloud(
font_path="/Library/Fonts/ipaexg.ttf",
width=600,
height=300,
prefer_horizontal=1,
background_color='white',
include_numbers=True,
colormap='tab20',
regexp=r"[\w']+",
).generate_from_text(tokenized_text)
# TF-IDFで Word Cloud作成
wc_1 = WordCloud(
font_path="/Library/Fonts/ipaexg.ttf",
width=600,
height=300,
prefer_horizontal=1,
background_color='white',
include_numbers=True,
colormap='tab20',
).generate_from_frequencies(tfidf_dict)
# それぞれ可視化
plt.rcParams["font.family"] = "IPAexGothic"
fig = plt.figure(figsize=(12, 12), facecolor="w")
ax = fig.add_subplot(2, 1, 1, title="単語の出現回数で作成")
ax.imshow(wc_0)
ax.axis("off")
ax = fig.add_subplot(2, 1, 2, title="TF-IDFで作成")
ax.imshow(wc_1)
ax.axis("off")
plt.show()
出来上がった図がこちら。
明らかに下のやつの方がいいですね。