Streamlit in Snowflake ) WordCloudで日本語を文字化けせずに表示する方法

## WordCloudで日本語を文字化けせずに表示する方法

### :star: 記事概要

![Scinario1](http://drive.google.com/uc?export=view&id=1uW4hhDItLaaF1AVTjA0BIntCXsgFOA4s)

以下に該当する方に有用な記事になっております
- **WordCloud** を **Streamlit in Snowflake** で使いたい!
- 日本語を表示する場合, フォントファイルを指定しないと文字化けしてしまう...🥺
- Streamlit in Snowflakeでは, どのようにフォントファイル指定するのか知りたい!


動画でサクッと把握したい方は, こちらの [[YouTube動画(2min)]](https://youtu.be/Dzbh2rp_CTs) をご覧ください

※ 以下, Streamlit in SnowflakeをSiSと表現します

### :star: WordCloudとは...
文章やテキストから単語の出現頻度にあわせて文字の大きさを変えて視覚化したグラフのことです
<img width="600", src="https://aiacademy.jp/media/wp-content/uploads/2023/01/chapter_001093_pGnPqePajodu.png">
出典: [【テキストマイニング】WordCloud（ワードクラウド）とは](https://aiacademy.jp/media/?p=3659#:~:text=%E3%83%AF%E3%83%BC%E3%83%89%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%EF%BC%88wordcloud%EF%BC%89%E3%81%A8%E3%81%AF,%E3%81%AF%E3%80%81%E5%B0%8F%E3%81%95%E3%81%8F%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82)

### :star: SiSでのWordCloudの基本構成
`wordcloud_sample1.py` に記載されているコードが基本の構成になっています
fit_wordsの引数に, 文字列と数値がペアを渡してあげることで, 
WordCloudの画像内で, 文字列が数値の値に応じた大きさで表現されます
~~~python:wordcloud_sample1.py
import streamlit as st
from wordcloud import WordCloud

# WordCloudの設定
wc = WordCloud().fit_words({"A": 100, "B": 10, "C": 1})

# 画像データの生成
st.image(wc.to_array())
~~~
※ パッケージに「wordcloud」の追加が必要です

↓ 実行結果
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657288/acc5d731-811e-5cfc-7aaf-a847502c44eb.png">


### :star: WordCloudの障壁
以下の `wordcloud_sample2.py` のように, **フォントを指定せずに** 
fit_wordsの引数に **日本語** の文字列を渡してしまうと, 
結果の画像にあるように文字化けしてしまいます...


~~~python:wordcloud_sample2.py
import streamlit as st
from wordcloud import WordCloud

# WordCloudの設定
wc = WordCloud().fit_words({"綾野": 100, "櫻木": 30, "影田": 40, "坂本": 1, "庄司": 50, "菊池": 20, "越川": 20, "白畑": 20)

# 画像データの生成
st.image(wc.to_array())
~~~
↓ 実行結果
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657288/ebbe8c10-1e4a-0865-edf3-c2473f3718a4.png">



#### :star: WordCloudでのフォント指定
以下の `wordcloud_sample3.py` のように,  
WordCloudの引数 **font_path** に フォントファイルの置き場所(パス)を渡すことで, 
該当のフォントを使用して画像を生成することができるようになります
~~~python:wordcloud_sample3.py
import streamlit as st
from wordcloud import WordCloud

# WordCloudの設定
wc = WordCloud(font_path = フォントファイルのパスを記載).fit_words({"綾野": 100, "櫻木": 30, "影田": 40, "坂本": 1, "庄司": 50, "菊池": 20, "越川": 20, "白畑": 20)

# 画像データの生成
st.image(wc.to_array())
~~~

### :star: Streamlit in Snowflakeの障壁
Snowflakeの場合, ファイルの置き場所としてはステージがあります。

![スクリーンショット 0005-12-21 16.04.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657288/9e5eb6ab-8a28-5bdd-c1bf-966994538df8.png)

しかし, 現状 font_pathの値として 
**ステージにアップロードしたフォントファイルのパスを指定しても
該当のフォントファイルを開くことができません...** 
(2023年12月20日時点)
~~~python:wordcloud_sample4.py
import streamlit as st
from wordcloud import WordCloud

# WordCloudの設定
wc = WordCloud(font_path = f"@CITIBIKE.PUBLIC.FONTS/gomarice_mukasi_mukasi.ttf").fit_words({"綾野": 100, "櫻木": 30, "影田": 40, "坂本": 1, "庄司": 50, "菊池": 20, "越川": 20, "白畑": 20)

# 画像データの生成
st.image(wc.to_array())
~~~
↓ 実行結果
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657288/bace3049-f07d-7aad-7e41-02bc775993a7.png">

WordCloudから呼び出すファイルはローカルに置いておく必要があります

#### :star: 解決策
内部ステージにアップロードしたフォントファイルを
Streamlit in Snowflakeの **/tmp/フォルダ配下にコピー** し, 
そのファイルを引数とすることで日本語をキレイに実現できます

~~~python:wordcloud_sample5.py
import io
from io import BytesIO
import streamlit as st
from wordcloud import WordCloud

# フォントファイルのパス (内部ステージ)
path = f"@CITIBIKE.PUBLIC.FONTS/gomarice_mukasi_mukasi.ttf";

# ファイルの読み込み
with session.file.get_stream(path, decompress=False) as f:
    s = f.read()

# BytesIO: メモリ上でバイナリデータを扱うための機能
with BytesIO() as bs:
    bs.write(s)
    content = bs.getvalue()

# SiSの仮フォルダ領域への書き込み
with open(f"/tmp/bom-added-gomarice_mukasi_mukasi.ttf", "wb") as s:
    s.write(content)

# WordCloudの設定
wc = WordCloud(font_path=f"/tmp/bom-added-gomarice_mukasi_mukasi.ttf").fit_words({"綾野": 100, "櫻木": 30, "影田": 40, "坂本": 1, "庄司": 50, "菊池": 20, "越川": 20, "白畑": 20)

# 画像データの生成
st.image(wc.to_array())
~~~
↓ 実行結果
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657288/c45ea154-7166-1bf1-553c-765349a02040.png">


### :information_desk_person_tone2: 引用 / 参考リソース
フォントファイル
　→ [昔々ふぉんと](https://fontfree.me/3132)


参考サイト
- [PythonのImageFontで使うフォントファイルをコード内に記述する](https://qiita.com/bem130/items/85ac1bfc56fe39950baf)　
- [Wordcloud - 🎈 Using Streamlit - Streamlit](https://discuss.streamlit.io/t/wordcloud/5714)
- [Pythonライブラリ(可視化)：WordCloud](https://note.com/kiyo_ai_note/n/n0d37f6e69f59)


### :kissing: 今さらながら自己紹介
Snowflake合同会社 SalesEngineerの櫻木優輝と申します。
私が作成したデモ動画が社内でバズり, 社内のFY23Q3のAwardを受賞しました。

「もっと社外に発信していこう」ということで, 
これからSnowflakeのアレコレをわかりやすく発信していきますので, 
皆様どうぞよろしくお願いいたします🙇‍♂️


### :star2: すこし宣伝

https://www.snowflake.com/build/japan/

2024年01月31日に開催されるBUILD Japanというイベントに登壇します！
「Snowflakeで完結!!
　モデル開発からビジネス活用まで真のエンドツーエンド機械学習」
 
 こちらのセッションめちゃめちゃ面白い内容になっているので
 ぜひご参加くださいっ