Power BI × Pythonで日本語ワードクラウド ～Pythonビジュアル編～


"Word Cloud"を前に悄然とせし者に捧ぐ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/205972/9979680f-d042-2a30-1572-4710ee4448f8.png)

## はじめに
Power BIで日本語テキストデータのワードクラウドを作ろうとした場合に，カスタムビジュアル"Word Cloud"を使用すると，上手く単語に分解されず，このように一部文章がそのまま表示されてしまいます。

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/205972/805ac82f-3247-df28-b328-54a3e7f056e1.png)|
|:-:|

／(^o^)＼ﾅﾝﾃｺｯﾀｲ

しかし，2018年8月のアップデートでPythonが使えるようになりました(※)ので，Pythonビジュアルを使用してワードクラウドを作成してみたいと思います。
※2018年9月現在，プレビュー版


## 環境構築
Power BIでPythonを使用する準備は
　[Python × PowerBI データ分析事始め【データ準備編】 - Qiita](https://qiita.com/h_kobayashi1125/items/afc55abf7e98581bcab3)
をご参照ください。


## 処理の流れ
1. 全テキストデータを連結
1. 形態素解析
1. スペース区切りで再結合
1. ワードクラウド生成

※2・3を行わないと，カスタムビジュアルを使った場合と同じ目に遭います。



## 実装
#### 0. データ・ビジュアル準備
今回は[自身のツイート履歴](https://help.twitter.com/ja/managing-your-account/how-to-download-your-twitter-archive)(CSV)をデータとして使用します。
データは予めPower BI上に取り込んでおきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/205972/0b5f3490-8185-9b0d-cda0-cebace1b0538.png)
[text]列がツイートの中身です。こちらをワードクラウドで可視化します。

Pythonビジュアルを配置し，[値]エリアに対象のデータ列を設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/205972/4dcc217f-9da4-ff5e-7c3d-842f5532795a.png)




データは**PandasのDataFrame**として読み込まれます。


#### 1. 全テキストデータを連結
ここからはPythonビジュアルのスクリプトエディターに記載していきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/205972/0ee7353d-4974-406c-0946-2480a3b713c7.png)


形態素分析を行うために，まず全テキストデータを結合します。

```python
all_text= ""
for s in dataset.loc[:,'text'].values:
    all_text += s
```

#### 2. 形態素解析
今回はjanomeを使って形態素解析を行います。もちろんMeCabでも構いません。

1で連結したテキストデータを```tokenize()```メソッドに渡します。

```python
from janome.tokenizer import Tokenizer
tok = Tokenizer()
tokens = tok.tokenize(all_text)
```

#### 3. スペース区切りで再結合
ワードクラウド上へ表示するにあたり，**有意義な品詞(名詞/動詞/形容詞/副詞)の原型のみ**を半角スペース区切りで結合します。
```token.part_of_speech.split(',')[0]```が品詞，```token.base_form```が原型です。

```python
words = ""
for token in tokens:
    if token.part_of_speech.split(',')[0] in ['名詞', '動詞', '形容詞', '副詞']:
        words = words + " " + token.base_form
```


#### 4. ワードクラウド生成
以上の下準備が済んだら，いよいよワードクラウドを生成します。
[amueller様のライブラリ](https://github.com/amueller/word_cloud)を使用するので，さほど難しいことはありません。

```python
from wordcloud import WordCloud
wordcloud = WordCloud(background_color="white"
                     ,width=800
                     ,height=500).generate(words)
```

あとはプロットするだけです。

```python
import matplotlib.pyplot as plt
plt.figure(figsize=(30,24))
plt.imshow(wordcloud)
plt.axis("off")
plt.show()
```

では，ここまでの結果を表示してみましょう。
スクリプトエディター右上の[スクリプトの実行] ![image.png](https://qiita-image-store.s3.amazonaws.com/0/205972/a1fe13fb-926b-2faa-161f-2d056ec63e9e.png)を押下します。

はい。

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/205972/1686ab5e-08e4-7e0b-98ff-82830b39a1f7.png)|
|:-:|

~~豆腐一丁！~~

#### 問題1. 文字化け
何もしないと日本語が文字化けしてしまいますので，フォントを指定してあげましょう。

```python
from wordcloud import WordCloud
fpath = "C:/hogehoge/Fonts/YuGothM.ttc"   # 任意の日本語フォントのパスを指定
wordcloud = WordCloud(background_color="white"
                     ,font_path=fpath
                     ,width=800
                     ,height=500).generate(words)
```

再度スクリプトを実行します。

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/205972/d607e82a-35ca-6c87-6370-eb2b932e1253.png)|
|:-:|
無事表示されました。


#### 問題2. 無用な単語の表示
さて，無事表示されたものの，「https」や「する」など，無個性な単語がいくつか混じっています。
そんなときはストップワードを指定しましょう。

```python
stop_words = [u'https', u'co', u'LINE', u'アカウント', u'YahooNewsTopics'
             ,u'news', u'linenews', u'Yahoo', u'ニュース', u'いる', u'する'
             ,u'ある', u'なる', u'れる', u'できる', u'ない', u'これ', u'こと'
             ,u'さん', u'られる', u'やる', u'てる']

wordcloud = WordCloud(background_color="white"
                      ,font_path=fpath
                      ,width=800
                      ,height=500
                      ,stopwords=set(stop_words)).generate(words)
```

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/205972/e0e34683-7170-24a6-d903-83a5eaa1f9f8.png)|
|:-:|
なかなかいい感じになりました。
いいと思ったことをつぶやく傾向があるのですかね。(meって何だ…)


## おまけ
#### マスキング
マスキングもできます。

せっかくなので，Twitterロゴでマスキングしてみましょう。

```python
import numpy as np
from PIL import Image
twitter_logo = np.array(Image.open("/hogehoge/Twitter_Logo.png"))   # 任意の画像パスを指定
```


ついでに色もそれっぽくします。

```python
def color_func(word, font_size, position, orientation, random_state, font_path):
    return 'deepskyblue'
```

表示すると・・・

```python
wordcloud = WordCloud(background_color="white"
                     ,font_path=fpath
                     ,color_func=color_func
                     ,width=800
                     ,height=500
                     ,mask=twitter_logo
                     ,stopwords=set(stop_words)).generate(words)
```
|![image.png](https://qiita-image-store.s3.amazonaws.com/0/205972/f72ce09b-6bda-e470-762d-d557769fa427.png)|
|:-:|

できた！


#### スライサー
Power BI上で動作しているので，スライサーも使えます。

試しに[timestamp]列をスライサーに設定し，今年のツイートに絞って表示してみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/205972/863efd62-960e-03c0-538f-e2c714ddecf5.png)

ここでは，Pythonスクリプトを変更したわけではないので，再実行は不要です。
自動的に再描画されるので，少し待ちます。

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/205972/7adbf334-235b-3f5d-184b-38fe9d5c565a.png)|
|:-:|

表示されました。
あまり変わっていませんが，「tabilabo」の代わりに「メディア」が台頭してきましたかね。


## まとめ
今回はPythonビジュアルを利用して，Power BI上で日本語ワードクラウドを表示してみました。
あくまで「Power BI上で日本語ワードクラウドを作成すること」が目的でしたので，テキストマイニングという観点ではイマイチな点もあるかと思いますが，ご容赦いただければ幸いです。

Power BI上で作成することで，他のチャートとの同時表示や分析対象の変更が手軽にできますので，アンケートの集計等に活用できるのではないかと思います。


以下，スクリプトです。

```python
from janome.tokenizer import Tokenizer
import numpy as np
from PIL import Image
from wordcloud import WordCloud
import matplotlib.pyplot as plt

# 全テキストデータを連結
all_text= ""
for s in dataset.loc[:,'分析対象列名'].values:
    all_text += s

# 形態素分析
tok = Tokenizer()
tokens = tok.tokenize(all_text)

# 解析結果のうち，名詞/動詞/形容詞/副詞の「原型」のみをスペース区切りで結合
words = ""
for token in tokens:
    if token.part_of_speech.split(',')[0] in ['名詞', '動詞', '形容詞', '副詞']:
        words = words + " " + token.base_form

# ストップワード指定
stop_words = [u'https', u'co', u'LINE', u'アカウント', u'YahooNewsTopics'
             ,u'news', u'linenews', u'Yahoo', u'ニュース', u'いる', u'する'
             ,u'ある', u'なる', u'れる', u'できる', u'ない', u'これ', u'こと'
             ,u'さん', u'られる', u'やる', u'てる']

# フォントカラー指定
def color_func(word, font_size, position, orientation, random_state, font_path):
    return 'deepskyblue'

# ワードクラウド生成
fpath = "C:/hogehoge/Fonts/hoge.ttc"   # 任意の日本語フォントのパスを指定
twitter_logo = np.array(Image.open("/hogehoge/hoge.png"))   # 任意の画像パスを指定

wordcloud = WordCloud(background_color="white"
                     ,font_path=fpath
                     ,color_func=color_func
                     ,width=800
                     ,height=500
                     ,mask=twitter_logo
                     ,stopwords=set(stop_words)).generate(words)

# プロット
plt.figure(figsize=(24,15))
plt.imshow(wordcloud)
plt.axis("off")
plt.show()
```


## 参考
- [PowerBI × Pythonで形態素解析をしてみよう - Qiita](https://qiita.com/ryoukom1216/items/657abcf0368f8b6da720)
- [Word Cloudで文章の単語出現頻度を可視化する。[Python] - Qiita]
(https://qiita.com/kenmatsu4/items/9b6ac74f831443d29074)
- [テキストマイニング：WordCloudで文系女子と理系女子のツイートを可視化してみた | パソコン工房 NEXMAG](https://www.pc-koubou.jp/magazine/2646)