Jupyter Notebook×MeCabで形態素解析！

こんにちは！今回はこちらの記事を見ていただきありがとうございます。
今回はタイトルにもある通り、最近Jupyter Notebook上で形態素解析エンジンである「MeCab」を動かす機会があったので備忘録として書かせていただきます。

ちなみに余談ですが名称は開発者の好物「和布蕪（めかぶ）」から取られたそうです。([引用](https://ja.wikipedia.org/wiki/MeCab#:~:text=%E5%90%8D%E7%A7%B0%E3%81%AF%E9%96%8B%E7%99%BA%E8%80%85%E3%81%AE,%EF%BC%89%E3%80%8D%E3%81%8B%E3%82%89%E5%8F%96%E3%82%89%E3%82%8C%E3%81%9F%E3%80%82&text=%E9%96%8B%E7%99%BA%E9%96%8B%E5%A7%8B%E5%BD%93%E5%88%9D%E3%81%AFChaSen,%E3%81%8B%E3%82%89%E9%96%8B%E7%99%BA%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%80%82))
すき家のめかぶオクラ牛丼美味しいですよね。👀

早速ですが導入手順を書いていきたいと思います！

# 1. Jupyterのインストール

以下のリンクからインストールしてください。説明文にある4つのExtension Packも一緒にインストールすると良いかと思います。

 https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter

# 2. MeCabのインストール

[こちらの参考にさせていただきました🙏](https://qiita.com/paulxll/items/72a2bea9b1d1486ca751#mecab%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)
Homebrewがない方は[インストール](https://brew.sh/index_ja.html)し、以下のコマンドを実行してください。

```
$ brew install mecab
$ brew install mecab-ipadic
```
# 3. pipコマンドでmecab-python3のインストール

```
$ pip install mecab-python3
```

# 4. インストール後にpython -cコマンドで実行可能かチェック

```
$ python -c "import MeCab"
```

※私はM1Macを使用しているのですが、こちらを実行する際に以下のエラーが発生しました。
```
mecab-python3 throws error "symbol not found in flat namespace '__ZN5MeCab11createModelEPKc'"
```

こちらの記事とissueを読み、以下のコメントに書いてあったコマンドを実行し、解消しました👍

https://zenn.dev/tomo25/articles/899f192724711b

https://github.com/coqui-ai/TTS/issues/2210

実行したコマンド
```
brew install --build-from-source mecab
ARCHFLAGS='-arch arm64' pip install --no-binary :all: --compile --use-pep517 --no-cache-dir --force mecab-python3
```
issueコメントURL

https://github.com/coqui-ai/TTS/issues/2210#issuecomment-1626890907

# 5. 実際にJupyter Notebook上で動かしてみる

今回はChat GPTで約400文字程度のダミーテキストを生成してもらい、そちらのテキストを形態素解析していきたいと思います。
~~ダミーテキストの内容がめっちゃふわふわ~~
単語を抽出順に出力する実装は[こちら](https://note.com/smkt_interview/n/nafebd60ae6bc)を参考にさせていただきました！

出力結果は以下の3つを基準にしてみました。
**・dict型形式**
**・同じワードがあった場合はインクリメントし、出現回数をカウント**
**・品詞の情報を同じオブジェクトに格納**

```python:test.ipynb
import MeCab
from collections import defaultdict

mecab_tagger = MeCab.Tagger()

text = '''あるところに、小さな森がありました。その森には美しい花々や色とりどりの鳥たちが暮らしていました。日が暮れると、満天の星が輝き、月が優しく見守ってくれました。 \
ある日、森の奥深くで不思議な生き物を見つけました。それはふわふわとした毛並みを持ち、大きな瞳を輝かせていました。子どもたちはその生き物を「ふわふわちゃん」と名付け、みんなで可愛がりました。 \
ふわふわちゃんは賢く、言葉を話すことができました。森の生物たちと友達になり、楽しい冒険を共有しました。彼らは時にはお互いを助け合い、時には笑い合い、困難を乗り越えてきました。 \
しかし、ある日、森に不穏な影が忍び寄りました。ふわふわちゃんが突然姿を消してしまったのです。子どもたちは心配し、探しに出かけましたが、見つけることができませんでした。 \
絶望的な気持ちで戻る子どもたちでしたが、ふわふわちゃんは突然姿を現し、安心させました。彼は遠くの地に行っていたのだそうです。どんな冒険をしていたのか、ふわふわちゃんは笑顔で語り始めました。 \
森の仲間たちはふわふわちゃんの話に夢中になり、ますます絆が深まりました。それからというもの、森はさらに楽しい場所になり、みんなが幸せに過ごしていったのでした。 \
'''

# defaultdictを用いてキーが存在しない場合のエラーを回避
part_of_kw_count_dict = defaultdict(lambda: {'count': 0, 'part_of_speech': ''})

# surface(単語)とfeature(単語が持つ品詞などの情報)の解析結果をnodeに代入
node = mecab_tagger.parseToNode(text)
while node:
    word = node.surface
    part_of_speech = node.feature.split(",")[0]
    part_of_kw_count_dict[word]['count'] += 1
    # 品詞の内容を入れる
    part_of_kw_count_dict[word]['part_of_speech'] = part_of_speech   
    # 次の形態素に進む
    node = node.next

sorted_part_of_kw_by_count = sorted(part_of_kw_count_dict.items(), key=lambda x: x[1]['count'], reverse=True)
sorted_kw_dict = dict(sorted_part_of_kw_by_count)
print(sorted_kw_dict)
```

#### 出力結果
※動詞や名詞のみ、という条件文を加えても良いかと思います👍
```python:出力結果
{'た': {'count': 22, 'part_of_speech': '助動詞'}, '、': {'count': 20, 'part_of_speech': '記号'}, '。': {'count': 17, 'part_of_speech': '記号'}, 'まし': {'count': 14, 'part_of_speech': '助動詞'}, 'が': {'count': 13, 'part_of_speech': '助詞'}, 'は': {'count': 11, 'part_of_speech': '助詞'}, 'の': {'count': 11, 'part_of_speech': '名詞'}, 'を': {'count': 11, 'part_of_speech': '助詞'}, 'に': {'count': 10, 'part_of_speech': '助詞'}, 'て': {'count': 8, 'part_of_speech': '助詞'}, '森': {'count': 7, 'part_of_speech': '名詞'}, 'ふわふわ': {'count': 7, 'part_of_speech': '副詞'}, 'たち': {'count': 6, 'part_of_speech': '名詞'}, 'ちゃん': {'count': 6, 'part_of_speech': '名詞'}, 'い': {'count': 4, 'part_of_speech': '動詞'}, 'と': {'count': 4, 'part_of_speech': '助詞'}, 'で': {'count': 4, 'part_of_speech': '助詞'}, 'し': {'count': 4, 'part_of_speech': '動詞'}, 'ある': {'count': 3, 'part_of_speech': '連体詞'}, '日': {'count': 3, 'part_of_speech': '名詞'}, 'な': {'count': 3, 'part_of_speech': '助動詞'}, '子ども': {'count': 3, 'part_of_speech': '名詞'}, 'なり': {'count': 3, 'part_of_speech': '動詞'}, 'でし': {'count': 3, 'part_of_speech': '助動詞'}, '': {'count': 2, 'part_of_speech': 'BOS/EOS'}, 'その': {'count': 2, 'part_of_speech': '連体詞'}, '生き物': {'count': 2, 'part_of_speech': '名詞'}, 'せ': {'count': 2, 'part_of_speech': '動詞'}, 'みんな': {'count': 2, 'part_of_speech': '名詞'}, 'こと': {'count': 2, 'part_of_speech': '名詞'}, 'でき': {'count': 2, 'part_of_speech': '動詞'}, '楽しい': {'count': 2, 'part_of_speech': '形容詞'}, '冒険': {'count': 2, 'part_of_speech': '名詞'}, '時には': {'count': 2, 'part_of_speech': '副詞'}, '突然': {'count': 2, 'part_of_speech': '副詞'}, '姿': {'count': 2, 'part_of_speech': '名詞'}, 'です': {'count': 2, 'part_of_speech': '助動詞'}, 'ところ': {'count': 1, 'part_of_speech': '名詞'}, '小さな': {'count': 1, 'part_of_speech': '連体詞'}, 'あり': {'count': 1, 'part_of_speech': '動詞'}, '美しい': {'count': 1, 'part_of_speech': '形容詞'}, '花': {'count': 1, 'part_of_speech': '名詞'}, '々': {'count': 1, 'part_of_speech': '記号'}, 'や': {'count': 1, 'part_of_speech': '助詞'}, '色とりどり': {'count': 1, 'part_of_speech': '名詞'}, '鳥': {'count': 1, 'part_of_speech': '名詞'}, '暮らし': {'count': 1, 'part_of_speech': '動詞'}, '暮れる': {'count': 1, 'part_of_speech': '動詞'}, '満天': {'count': 1, 'part_of_speech': '名詞'}, '星': {'count': 1, 'part_of_speech': '名詞'}, '輝き': {'count': 1, 'part_of_speech': '動詞'}, '月': {'count': 1, 'part_of_speech': '名詞'}, '優しく': {'count': 1, 'part_of_speech': '形容詞'}, '見守っ': {'count': 1, 'part_of_speech': '動詞'}, 'くれ': {'count': 1, 'part_of_speech': '動詞'}, '奥深く': {'count': 1, 'part_of_speech': '形容詞'}, '不思議': {'count': 1, 'part_of_speech': '名詞'}, '見つけ': {'count': 1, 'part_of_speech': '動詞'}, 'それ': {'count': 1, 'part_of_speech': '名詞'}, '毛並み': {'count': 1, 'part_of_speech': '名詞'}, '持ち': {'count': 1, 'part_of_speech': '動詞'}, '大きな': {'count': 1, 'part_of_speech': '連体詞'}, '瞳': {'count': 1, 'part_of_speech': '名詞'}, '輝か': {'count': 1, 'part_of_speech': '動詞'}, '「': {'count': 1, 'part_of_speech': '記号'}, '」': {'count': 1, 'part_of_speech': '記号'}, '名付け': {'count': 1, 'part_of_speech': '動詞'}, '可愛がり': {'count': 1, 'part_of_speech': '動詞'}, '賢く': {'count': 1, 'part_of_speech': '形容詞'}, '言葉': {'count': 1, 'part_of_speech': '名詞'}, '話す': {'count': 1, 'part_of_speech': '動詞'}, '生物': {'count': 1, 'part_of_speech': '名詞'}, '友達': {'count': 1, 'part_of_speech': '名詞'}, '共有': {'count': 1, 'part_of_speech': '名詞'}, '彼ら': {'count': 1, 'part_of_speech': '名詞'}, 'お互い': {'count': 1, 'part_of_speech': '名詞'}, '助け合い': {'count': 1, 'part_of_speech': '動詞'}, '笑い': {'count': 1, 'part_of_speech': '動詞'}, '合い': {'count': 1, 'part_of_speech': '動詞'}, '困難': {'count': 1, 'part_of_speech': '名詞'}, '乗り越え': {'count': 1, 'part_of_speech': '動詞'}, 'き': {'count': 1, 'part_of_speech': '動詞'}, 'しかし': {'count': 1, 'part_of_speech': '接続詞'}, '不穏': {'count': 1, 'part_of_speech': '名詞'}, '影': {'count': 1, 'part_of_speech': '名詞'}, '忍び寄り': {'count': 1, 'part_of_speech': '動詞'}, '消し': {'count': 1, 'part_of_speech': '動詞'}, 'しまっ': {'count': 1, 'part_of_speech': '動詞'}, '心配': {'count': 1, 'part_of_speech': '名詞'}, '探し': {'count': 1, 'part_of_speech': '動詞'}, '出かけ': {'count': 1, 'part_of_speech': '動詞'}, '見つける': {'count': 1, 'part_of_speech': '動詞'}, 'ませ': {'count': 1, 'part_of_speech': '助動詞'}, 'ん': {'count': 1, 'part_of_speech': '助動詞'}, '絶望': {'count': 1, 'part_of_speech': '名詞'}, '的': {'count': 1, 'part_of_speech': '名詞'}, '気持ち': {'count': 1, 'part_of_speech': '名詞'}, '戻る': {'count': 1, 'part_of_speech': '動詞'}, '現し': {'count': 1, 'part_of_speech': '動詞'}, '安心': {'count': 1, 'part_of_speech': '名詞'}, 'さ': {'count': 1, 'part_of_speech': '動詞'}, '彼': {'count': 1, 'part_of_speech': '名詞'}, '遠く': {'count': 1, 'part_of_speech': '名詞'}, '地': {'count': 1, 'part_of_speech': '名詞'}, '行っ': {'count': 1, 'part_of_speech': '動詞'}, 'だ': {'count': 1, 'part_of_speech': '助動詞'}, 'そう': {'count': 1, 'part_of_speech': '名詞'}, 'どんな': {'count': 1, 'part_of_speech': '連体詞'}, 'か': {'count': 1, 'part_of_speech': '助詞'}, '笑顔': {'count': 1, 'part_of_speech': '名詞'}, '語り': {'count': 1, 'part_of_speech': '動詞'}, '始め': {'count': 1, 'part_of_speech': '動詞'}, '仲間': {'count': 1, 'part_of_speech': '名詞'}, '話': {'count': 1, 'part_of_speech': '名詞'}, '夢中': {'count': 1, 'part_of_speech': '名詞'}, 'ますます': {'count': 1, 'part_of_speech': '副詞'}, '絆': {'count': 1, 'part_of_speech': '名詞'}, '深まり': {'count': 1, 'part_of_speech': '動詞'}, 'それから': {'count': 1, 'part_of_speech': '接続詞'}, 'という': {'count': 1, 'part_of_speech': '助詞'}, 'もの': {'count': 1, 'part_of_speech': '名詞'}, 'さらに': {'count': 1, 'part_of_speech': '副詞'}, '場所': {'count': 1, 'part_of_speech': '名詞'}, '幸せ': {'count': 1, 'part_of_speech': '名詞'}, '過ごし': {'count': 1, 'part_of_speech': '動詞'}, 'いっ': {'count': 1, 'part_of_speech': '動詞'}}
```

# まとめ
今回は**Jupyter Notebook×MeCab**の構成で形態素解析を実行してみました！
もし参考になった、もしくはいいなと思ったら**LGTM**いただけると励みになります！

それではみなさん、**_Happy Hacking!!!!_**