言語処理100本ノック-37(pandas使用):頻度上位10語

[言語処理100本ノック 2015](http://www.cl.ecei.tohoku.ac.jp/nlp100/)[「第4章: 形態素解析」](http://www.cl.ecei.tohoku.ac.jp/nlp100/#ch4)の[37本目「頻度上位10語」](http://www.cl.ecei.tohoku.ac.jp/nlp100/#sec37)記録です。
今回はグラフ表示ということで`matplotlib`を使います。`matplotlib`で誰もが陥ると思われる[「豆腐問題」](https://www.google.com/search?q=matplotlib+%E8%B1%86%E8%85%90)(日本語が表示される豆腐っぽい文字がグラフ上に表示される現象)に対応します。

# 参考リンク

|リンク|備考|
|:--|:--|
|[037.頻度上位10語.ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/04.%E5%BD%A2%E6%85%8B%E7%B4%A0%E8%A7%A3%E6%9E%90/037.%20%E9%A0%BB%E5%BA%A6%E4%B8%8A%E4%BD%8D10%E8%AA%9E.ipynb)|回答プログラムのGitHubリンク|
|[素人の言語処理100本ノック:37](http://qiita.com/segavvy/items/72863888e51fabd79295)|多くのソース部分のコピペ元|
|[MeCab公式](https://taku910.github.io/mecab/)|最初に見ておくMeCabのページ|

# 環境

|種類|バージョン|内容|
|:--|:--|:--|
|OS|Ubuntu18.04.01 LTS|仮想で動かしています|
|pyenv|1.2.16|複数Python環境を使うことがあるのでpyenv使っています|
|Python|3.8.1|pyenv上でpython3.8.1を使っています<br>パッケージはvenvを使って管理しています|
|Mecab|0.996-5|apt-getでインストール|

上記環境で、以下のPython追加パッケージを使っています。通常のpipでインストールするだけです。

|種類|バージョン|
|:--|:--|
|matplotlib|3.1.3|
|pandas|1.0.1|


# [第4章: 形態素解析](http://www.cl.ecei.tohoku.ac.jp/nlp100/#ch4)
## 学習内容
> 夏目漱石の小説『吾輩は猫である』に形態素解析器MeCabを適用し，小説中の単語の統計を求めます．
>> 形態素解析, MeCab, 品詞, 出現頻度, Zipfの法則, [matplotlib](http://matplotlib.org/), [Gnuplot](http://www.gnuplot.info/)

## ノック内容
> 夏目漱石の小説『吾輩は猫である』の文章（[neko.txt](http://www.cl.ecei.tohoku.ac.jp/nlp100/data/neko.txt)）をMeCabを使って形態素解析し，その結果をneko.txt.mecabというファイルに保存せよ．このファイルを用いて，以下の問に対応するプログラムを実装せよ．

なお，問題37, 38, 39は[matplotlib](http://matplotlib.org/)もしくは[Gnuplot](http://www.gnuplot.info/)を用いるとよい．

### [37. 頻度上位10語](http://www.cl.ecei.tohoku.ac.jp/nlp100/#sec37)
> 出現頻度が高い10語とその出現頻度をグラフ（例えば棒グラフなど）で表示せよ．

# 回答
## 回答プログラム [037.頻度上位10語.ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/04.%E5%BD%A2%E6%85%8B%E7%B4%A0%E8%A7%A3%E6%9E%90/037.%20%E9%A0%BB%E5%BA%A6%E4%B8%8A%E4%BD%8D10%E8%AA%9E.ipynb)

```python
import pandas as pd
import matplotlib.pyplot as plt

plt.rcParams['font.family'] = 'IPAexGothic'

def read_text():
    # 0:表層形(surface)
    # 1:品詞(pos)
    # 2:品詞細分類1(pos1)
    # 7:基本形(base)
    df = pd.read_table('./neko.txt.mecab', sep='\t|,', header=None, 
                       usecols=[0, 1, 2, 7], names=['surface', 'pos', 'pos1', 'base'], 
                       skiprows=4, skipfooter=1 ,engine='python')
    return df[(df['pos'] != '空白') & (df['surface'] != 'EOS') & (df['pos'] != '記号')]

df = read_text()

df['surface'].value_counts()[:10].plot.bar()

# 助詞と助動詞を除外
df[~df['pos'].str.startswith('助')]['surface'].value_counts()[:10].plot.bar()
```

## 回答解説
### 豆腐(グラフ文字化け対応)対応
以下の記事を参考にして豆腐(グラフ文字化け対応)対応をしました。対応方法はOSおよびPython環境(pyenv使用など)に大きく依存するので注意ください。
2021/11/25追記: [japanize-matplotlib](https://pypi.org/project/japanize-matplotlib/)という神ライブラリができていました。[記事「1分で簡単！Matplotlibの日本語対応を徹底解説！」](https://ai-inter1.com/matplotlib-japanize/)参照。

- [matplotlibの日本語文字化けを解決する](https://qiita.com/katuemon/items/5c4db01997ad9dc343e0#%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%81%AE%E5%89%8A%E9%99%A4)
- [matplotlibの日本語文字化けについて](http://oyaryo.blogspot.com/2018/03/matplotlib.html)

#### 1. フォントインストール
`apt-get`でフォントをインストールします

```bash
apt-get install fonts-ipaexfont
```

#### 2. キャッシュ削除
`matplotlib`のフォントキャッシュである以下のファイルを物理削除します。2つの違いがわかっていないのですが、「キャッシュは消してもいいや」の感覚で削除しました。

- /Users/ユーザー名/.cache/matplotlib/fontlist-v300.json
- /Users/ユーザー名/.cache/matplotlib/fontlist-v310.json


#### 3. Pythonでフォント指定
Python上の以下の設定でグラフ出力するフォントを指定します。これで「豆腐」対応完了です。

```python:
plt.rcParams['font.family'] = 'IPAexGothic'
```

### グラフ出力
`pandas`だと`plot`を使ってそのまま出力できるので非常に便利です。

```python:
df['surface'].value_counts()[:10].plot.bar()

# 助詞と助動詞を除外
df[~df['pos'].str.startswith('助')]['surface'].value_counts()[:10].plot.bar()
```

### 出力結果(実行結果)
プログラム実行すると以下の結果が出力されます。やはり数字だけで見るよりグラフ化した方がわかりやすいですね。

#### 全単語
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/222e45f4-6dd2-3b31-0aed-b341e8a7c7a4.png)

### 助詞と助動詞を除外した単語
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/53fbd454-0646-4180-2d67-5d3eb2ed27b2.png)