形態素解析とキーワード可視化：Pythonによるテキストデータ分析の基礎

# 0. はじめに
こんにちは！データ分析の世界では、テキストデータは洞察に満ちた宝庫です。今回は、Pythonを用いてテキストデータから価値ある情報を抽出し、それを視覚化する方法をご紹介します。
本稿では、芥川龍之介の羅生門を例に、形態素解析からキーワードの抽出、そしてキーワード可視化までのプロセスを解説します。

<img width="800", src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565029/40cf25eb-ae7e-b5aa-708e-9397d3d2023f.png" alt="DALL-E3によって生成した形態素解析のイメージ図">
DALL-E3によって生成した形態素解析のイメージ図

# 1. 必要なライブラリ
この分析には以下のPythonライブラリを使用しています：

### 1.1 Pandas
Pandasは、Pythonのデータ分析と操作のための強力なライブラリです。データサイエンティストやアナリストに広く愛用されています。このライブラリは、1次元のシリーズと2次元のデータフレームの二つの主要なデータ構造を提供します。これらは異なるデータ型を持つことができ、柔軟なデータ操作を可能にします。Pandasは多様なデータソースからのデータ読み込みや書き出しをサポートし、データクリーニングやフィルタリング、ソート、グループ化などの操作を容易に行えます。また、基本的な統計計算から複雑なデータ操作まで、幅広い統計関数を備えています。

### 1.2 Janome
Janomeは、Pythonで書かれた日本語のテキストを解析するための形態素解析エンジンです。このエンジンは、日本語の文章を単語とその品詞情報に分解し、テキスト分析や自然言語処理のタスクを容易にします。Janomeは、使いやすく、インストールが簡単で、カスタム辞書の作成や利用も可能です。高速で正確な解析能力を持ちながら、シンプルなインターフェースを提供します。

### 1.3 scikit-learn
scikit-learnは、機械学習のためのPythonライブラリです。このライブラリは、分類、回帰、クラスタリングなどの多様な機械学習アルゴリズムを提供しています。データ前処理機能も充実しており、標準化や正規化、欠損値処理などを行うことができます。特徴選択や次元削減などの高度な機能も備えており、データを機械学習に適した形式に変換するのに役立ちます。また、データの前処理から学習モデルの訓練、評価までを一連のステップとして扱うパイプライン機能もあります。

### 1.4 wordcloud
wordcloudは、テキストデータ内の単語の頻度に基づいて、視覚的な単語のクラウドを生成するライブラリです。単語の頻度に応じてサイズが異なる単語クラウドを生成し、テキストデータの中で最も重要なキーワードを一目で理解するのに役立ちます。フォント、色、形状などの外観をカスタマイズすることができ、使用法は非常にシンプルです。単語の頻度データから直接クラウドを生成でき、データの視覚化に優れたツールとして広く使われています。

# 2. データの読み込みとPandasの使用
それではさっそく実装してみましょう。まず、Pandasを使用してテキストファイルを読み込み、データフレーム形式で整理します。PandasのDataFrameは、データを表形式で扱うための強力なツールです。ここでは、テキストファイルの各行をデータフレームの行として格納しています。

```python: Pandasでのデータ読み込み
import pandas as pd

# テキスト読み込み
file_path = './novels/rashomon-utf8.txt'
with open(file_path, 'r', encoding='utf-8') as file:
    lines = file.readlines()

# データをPandasのDataFrameに格納
df = pd.DataFrame(lines, columns=['テキスト'])

# 不要な空行の削除
df.dropna(subset=['テキスト'], inplace=True)
```

# 3. 形態素解析
次にJanomeを使用してテキストから名詞を抽出します。

```python: 形態素分析
from janome.tokenizer import Tokenizer

# Janomeを用いた形態素解析関数
t = Tokenizer()
def extract_nouns(text, tokenizer):
    words = [token.surface for token in tokenizer.tokenize(text) if token.part_of_speech.startswith('名詞')]
    return ' '.join(words)

# 各行に形態素解析を適用し、名詞のみを抽出
df['名詞のみ'] = df['テキスト'].apply(lambda x: extract_nouns(x, t))
```

ここではJanomeを使って、テキストデータから名詞のみを抽出するプロセスを示しています。始めに、`Tokenizer`のインスタンスを作成します。このインスタンスは、テキストを形態素に分解するために使われます。

続いて、`extract_nouns`という関数を定義します。この関数は、`tokenizer.tokenize(text)`を使用して、与えられたテキストを形態素に分解し、それぞれの形態素に関する情報を含むトークンを生成します。各トークンには表層形（`token.surface`）や品詞情報（`token.part_of_speech`）が含まれます。リスト内包表記を用いて、品詞が名詞であるすべてのトークンの表層形をリストに収集し、そのリストの要素をスペースで連結して、名詞のみの文字列を生成します。

最後に、元のテキストデータが含まれるDataFrameの列df['テキスト']に.apply()メソッドを使用し、その列の各行に対して`extract_nouns`関数を適用します。こうすることで、各行のテキストから抽出された名詞のみが含まれる新しい列がDataFrameに追加されることになります。

# 4. TF-IDFベクトル化とキーワード抽出
次に名詞化されたテキストデータをscikit-learnのTF-IDF（Term Frequency-Inverse Document Frequency）ベクトル化機能を使用して、重要なキーワードを特定します。

```python
from sklearn.feature_extraction.text import TfidfVectorizer

# TF-IDFを用いてベクトル化し、キーワードを抽出
vectorizer = TfidfVectorizer(stop_words=['こと', 'ため', 'よう', 'もの', 'これ', 'それ', 'どこ', 'そこ', 'たい', 'ほか', 'さっき', 'びと'])
X = vectorizer.fit_transform(df['名詞のみ'])

# ベクトル化されたデータをDataFrameに変換
df_vectorized = pd.DataFrame(X.toarray(), columns=vectorizer.get_feature_names_out())

# TOP30のキーワードを特定
top_30_keywords = df_vectorized.sum().nlargest(30)
print("TOP30のキーワード:")
print(top_30_keywords)
```

まず、`TfidfVectorizer`のインスタンス`vectorizer`を作成し、「こと」「ため」「よう」などの一般的なストップワードを指定します。これらのストップワードはベクトル化の過程で無視されるため、より有意義なキーワードに焦点を当てることができます。

次に、`vectorizer.fit_transform()`メソッドを使用して、形態素解析で抽出された名詞のみを含む`df['名詞のみ']`列をTF-IDFベクトルに変換します。このメソッドは各名詞のTF-IDFスコアを計算し、それに基づいてテキストをベクトル化します。この結果は疎行列（多くの要素がゼロである行列）として返されます。

続いて、疎行列を通常の配列に変換し、その結果をPandasのDataFrameに変換します。この新しいDataFrame（`df_vectorized`）には、各単語のTF-IDFスコアが列として含まれています。列の名前は`vectorizer.get_feature_names_out()`メソッドを使用して取得します。

最終ステップとして、各単語のスコアを合計し、スコアが最も高い上位30のキーワードを特定します。これらのキーワードはテキストにおいて特に重要な意味を持つ単語と見なされます。このようにTF-IDFベクトル化を用いてテキストデータの重要な特徴を抽出し、分析や機械学習アプリケーションで扱いやすい形式に変換する役割を果たしています。それでは、これらTOP30キーワード（の一部）を実際に出力してみます。

```
TOP30のキーワード:
下人     4.460732
老婆     4.065640
死骸     2.240533
梯子     2.002312
羅生門    1.649780
饑死     1.490376
死人     1.222656
太刀     1.123988
髪の毛    1.103031
やみ     1.058868
おのれ    1.000000
...
```
なにやら不気味なワードが並んでいます。。


# 5. キーワードの可視化

次は、matplotlibとwordcloudライブラリを使用して、テキストデータから抽出したトップ30のキーワードを視覚的に表現してみましょう。

```python: wordcloudでのデータ可視化

from matplotlib import pyplot as plt
from wordcloud import WordCloud

# 日本語フォント設定（wordcloud用）
plt.rcParams['font.family'] = 'Meiryo'

# ワードクラウドの作成
wordcloud = WordCloud(width=800, height=400, background_color='white',
            font_path='C:\Windows\Fonts\meiryo.ttc').generate_from_frequencies(top_30_keywords)

# ワードクラウドの表示
plt.figure(figsize=(12, 6))
plt.imshow(wordcloud, interpolation='bilinear')
plt.title('キーワードTOP30', fontsize=16)
plt.axis('off')
plt.tight_layout()
plt.show()
```
日本語フォント「Meiryo」がwordcloudの生成に使用されるように設定します。これにより、生成されるワードクラウドにおいて日本語が正しく表示されるようになります。

その後、`WordCloud`クラスのインスタンスを生成します。このインスタンスを作成する際に、幅（`width`）と高さ（`height`）、背景色（`background_colo`r）、およびフォントパス（`font_path`）などを指定します。そして、`generate_from_frequencies`メソッドを使用して、先に特定されたトップ30のキーワードとその頻度を基にワードクラウドを生成します。キーワードが大きいほど、テキストデータ内での頻度が高いことを示します。

ワードクラウドの表示のために、`plt.figure`を用いて図のサイズを設定し、`plt.imshow`を使用してワードクラウドを表示します。`interpolation='bilinear'`は画像の滑らかさを向上させるためのオプションです。タイトル、軸の非表示、レイアウトの調整が行われた後、`plt.show`を使ってワードクラウドを表示します。


![ダウンロード (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565029/6f320c03-9f43-5ba4-f8d6-c02d8930978b.png)

ますます不気味な感じしますね。。

# 6. まとめ
形態素解析とキーワードの可視化は、テキストデータの深い理解に繋がる手法です。Pandas, Janome, scikit-learn, wordcloudといったライブラリを駆使することで、データから新たな洞察を得ることが可能です。本稿で紹介した技術を活用して、さまざまなテキストデータを探索し、価値ある発見をしていただければ幸いです。

# 7. 参考文献

https://www.aozora.gr.jp/cards/000879/card127.html

＊この記事はcode snippetをもとにChatGPTにつくらせています。