Textheroを使ってテキストデータを可視化する

[Texthero](https://github.com/jbesomi/texthero)というpythonライブラリを使って、テキストデータのワードクラウドや主成分分析によるデータの散布図を表示してみる

自分でまとめたもの → https://github.com/youichiro/texthero-sample

## 準備
プロジェクトディレクトリを作成する

```sh
$ mkdir texthero-sample
$ cd texthero-sample
```

必要なライブラリをインストールする

```bash
$ pip install texthero
```

mecabを使えるようにする

```bash
$ pip install mecab-python3 ipadic
```

ワードクラウドを表示するときに日本語が文字化けしたので、日本語フォントをダウンロードする

```bash
$ mkdir fonts
$ cd fonts
$ wget https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip
$ unzip NotoSansCJKjp-hinted.zip -d NotoSansCJKJP
$ cd ..
```

ストップワードを用意する
調べたらよく出てきたストップワードリストをダウンロードする

```bash
$ mkdir dicts
$ cd dicts
$ wget http://svn.sourceforge.jp/svnroot/slothlib/CSharp/Version1/SlothLib/NLP/Filter/StopWord/word/Japanese.txt -O stopwords.txt
$ cd ..
```

試す用にlivedoorニュースコーパスを取得する
ダウンロードするためのpythonスクリプトがあったのでそれを使う

```bash
$ wget https://gist.githubusercontent.com/nxdataka/48a27b2e1c3f029e7f25e66dba4b6dde/raw/75b56c34869c6b290cdb54a0925f34baeace021a/ldn2csv.py
$ python ldn2csv.py -o data/livedoornews.csv
```

## 前処理

```python
import texthero as hero
import pandas as pd
import MeCab
import ipadic

# DataFrameの用意
df = pd.read_csv('data/livedoornews.csv')
df.rename(columns={'body': 'text'}, inplace=True)
df.rename(columns={'media': 'topic'}, inplace=True)
df.dropna(how='any', inplace=True)
df = df[['topic', 'text']]

# ストップワードを用意する
stopwords = pd.read_csv('dicts/stopwords.txt', squeeze=True)
stopwords = stopwords.values.tolist()

# mecabで形態素解析し、指定した品詞の単語のみ抽出した分かち書きを行う関数を用意する
tagger = MeCab.Tagger(ipadic.MECAB_ARGS)
pos_list = ['名詞', '動詞', '形容詞']

def wakati(text):
    node = tagger.parseToNode(text)
    words = []

    while node:
        pos = node.feature.split(',')[0]
        surface = node.surface
        if pos in pos_list and surface not in stopwords:
            words.append(surface)
        node = node.next
    return ' '.join(words)
    
# 分かち書きを行う
df['wakati_text'] = df['text'].apply(lambda x: wakati(x))

# 前処理を行う
df['wakati_text'] = hero.clean(df['wakati_text'], pipeline=[
    hero.preprocessing.remove_digits,  # 数字を削除
    hero.preprocessing.remove_whitespace,  # 余計な空白を削除
])
```

## ワードクラウドを表示する
### 映画に関する記事のワードクラウド

```python
movie_text = df[df['topic'] == 'movie-enter']]['wakati_text']
hero.visualization.wordcloud(movie_text, font_path='fonts/NotoSansCJKJP/NotoSansCJKjp-Regular.otf', colormap='viridis', width=500, height=400, background_color='White')
```

![スクリーンショット 2021-03-13 2.05.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/06d99123-c89d-ea6e-deff-621e26b6bece.png)


### スマホに関する記事のワードクラウド

```python
movie_text = df[df['topic'] == 'smax']]['wakati_text']
hero.visualization.wordcloud(movie_text, font_path='fonts/NotoSansCJKJP/NotoSansCJKjp-Regular.otf', colormap='viridis', width=500, height=400, background_color='White')
```

![スクリーンショット 2021-03-13 2.05.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/1caee4e9-79d2-c77c-a4b1-60905351c422.png)


## 主成分分析(PCA)による散布図を表示する
```python
df['pca'] = df['wakati_text'].pipe(hero.tfidf).pipe(hero.pca)
hero.scatterplot(df, 'pca', color='topic', title='topic')
```

![スクリーンショット 2021-03-13 2.43.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/dc3742d0-5a57-870d-bf70-95b5dba0bcf1.png)


## 参考
- [texthero](https://github.com/jbesomi/texthero)
- [ipadic-py](https://github.com/polm/ipadic-py)
- [テキスト前処理と可視化が楽チンな『Texthero』使ってみた](https://qiita.com/h_yuma/items/c055c2fa801d0d60e63e)