プロ野球の実況ツイートからファンの民度を測ってみた

# はじめに

> プロ野球(NPB)がある程度わかる人向けの記事です。
> ちなみにわたしは🐯ファンですが，特定のファンを悪く言う目的はない，ということを理解した上で見てください。

以前，こんなニュースがありました。
> - [巨人の藤浪〝失礼動画〟流出騒動　球団が公式ツイッターで謝罪](https://news.yahoo.co.jp/articles/b75708d5787cee3a9572792452da030537afa10d "巨人の藤浪〝失礼動画〟流出騒動　球団が公式ツイッターで謝罪")
> - [「おまえ」で呼ぶのは失礼？　中日の応援歌自粛に賛否 ](https://www.nikkei.com/article/DGXMZO47172240Q9A710C1CC0000/ "「おまえ」で呼ぶのは失礼？　中日の応援歌自粛に賛否")

プロ野球の応援マナーに関連したニュースが元となって，Twitterで議論が巻き起こるってたまにありますよね。ニュース自体に言及するというよりも，違うファン同士で「おまえらのほうがマナー悪いやんけ！」みたいな言い合い。よく見ます。
また，他球団への悪口やヤジ以外にも，自分の応援するチームの選手にも過激な言葉を吐く人もいたり。


実際，こういう**民度**の低い言葉ってどのくらいあるんだろう？ 
**民度**の良し悪しは，球団によってどのくらい違うんだろう？

という疑問を感じたので，今回はこれを簡単に分析していきます。
分析対象は，Twitterに投稿された実況ツイートです。
つまり，あくまでも**「Twitter民」の民度**ということをお忘れなく！


# 民度の定義

今回は，分析を簡単にするために，ヤジ・悪口だと思われる単語（ここでは<font color="red">「ちくちく言葉」</font>と呼びます）を定義し，その単語が含まれているツイートの割合を計算して，民度の低さを測ります。
ついでに，民度の高さ（ファンの優しさ）も同じように定義して，<font color="blue">「ふわふわ言葉」</font>の割合を計算してみます。

これらを「ちくちく度」「ふわふわ度」として，下のように計算します。

$$チームＡのファンのちくちく度=\frac{ちくちく言葉が入っているチームＡのツイート数}{チームＡのツイート数}$$
$$チームＡのファンのふわふわ度=\frac{ふわふわ言葉が入っているチームＡのツイート数}{チームＡのツイート数}$$


# 実験方法と結果

実験方法の概要はこのようになっています。

1. ツイートの収集  
2. 実況ツイートの言語をモデル化  
3. <font color="red">ちくちく言葉</font>・<font color="blue">ふわふわ言葉</font>の単語を定義  
4. <font color="red">ちくちく度</font>・<font color="blue">ふわふわ度</font>の計算  

次から具体的に説明していきます。

## ツイートの収集

**野球の試合時間内に投稿されたツイートを各球団のハッシュタグを元に収集**

以前書いた記事「[プロ野球の実況ツイートを全部取得する](https://qiita.com/non-caffeine/items/a297a8b72f16308b69a0 "プロ野球の実況ツイートを全部取得する")」の方法でツイートを収集しました。
今回の実験では，2019年度のデータを扱います。

球団ごとの，ツイートを取得した試合数とツイートの総数は以下の通りです。

|     球団名   |     試合数    |    ツイート総数       |
|:----------------:|:------------------:|:------------------:|
| 巨人             |127|   590634       |
| 中日             |125|  250771         |
| 広島             |119|  442592         |
| ヤクルト          |122| 400029          |
| 阪神             |128| 428525         |
| ＤｅＮＡ          |127| 564144      | 
| 日本ハム	   |120|   415629       |  
| ソフトバンク       |125|  487349         | 
| 楽天             |122|  256291         |
| 西武             |123| 528261          |
| ロッテ            |122| 395208         | 
| オリックス        |121| 13710      |

※ オリックスに関しては，取得できたツイートが少なかったので，今回は省きます。ごめんなさい...




## 実況ツイートの言語をモデル化

**ツイートを前処理してWord2Vecのモデルを学習**

### 前処理

**テキストのクリーニング**
以下の処理等を行います

- URL，ハッシュタグ，スペース等の除去
- ＠以下の文字の除去
- 数字とアルファベットを半角文字に統一

**形態素解析による単語分割**

▼ [mecab-ipadic-neologd](https://github.com/neologd/mecab-ipadic-neologd "mecab-ipadic-neologd")の辞書を使って，mecabによる形態素解析

```python

def bow(mecab_dict,text):
    parts = ('名詞','形容詞','形容動詞','副詞','動詞','連体詞','感動詞','接続詞','記号')
    parsed = mecab_dict.parse(str(text))
    lines = parsed.split('\n')  # 解析結果を1行（1語）ごとに分けてリストにする
    lines = lines[0:-2]  # 後ろ2行は不要なので削除
    w_l = []
    for word in lines:
	l = re.split('\t|,', word)
	d_ = {'Surface': l[0], 'POS1': l[1]}
	if d_['POS1'] in parts:
	    w_l.append(d_['Surface'])
    return w_l


mecab_dict = MeCab.Tagger('../data/mecab-ipadic-neologd/')

# text_list = ['大山ツーベースでチャンス','いやいや、今の結構危なかったよ。', ...]

words_list = []
for text in text_list:
    words = bow(mecab_dict,text)
    words_list.append(words)

# words_list = [['大山','ツーベース','で','チャンス'],\
#                ['いやいや','、','今','の','結構','危なかっ','た','よ','。']]
```

### Word2Vecのモデルを学習

▼ [gensim](https://radimrehurek.com/gensim/ "gensim")の[Word2Vec](https://radimrehurek.com/gensim/models/word2vec.html "Word2Vec")ライブラリを使って，実況ツイートをコーパスとした言語モデルを学習

```python


def train_word2vec(all_words_list,vecsize,window,min_count,iter_num):
    model = word2vec.Word2Vec(all_words_list,size=vecsize\
            , window=window, min_count=min_count, iter=iter_num)
    model.save('モデルのファイル名.model')


vecsize = 300
window = 10
min_count = 5
iter_num = 5
train_word2vec(words_list,vecsize,window,min_count,iter_num)

```

▼ モデルがちゃんと学習できているか確認，

```python

def word2vec_model_check(model,p_words,n_words):
	results = model.wv.most_similar(positive=p_words,negative=n_words,topn=10)
	print('model.wv.most_similar(positive=',p_words,',negative=',n_words,')')
	for result in results:
		print(result)
	return results

model = word2vec.Word2Vec.load('モデルのファイル名.model')


p_words, n_words = ['ラミレス'],[]
word2vec_model_check(model,p_words,n_words)

"""
# 実行結果
model.wv.most_similar(positive= ['ラミレス'] ,negative= [] )
('平石', 0.794029951095581)
('工藤', 0.7856395244598389)
('緒方', 0.7593538761138916)
('与田', 0.7247989177703857)
('辻', 0.7119660377502441)
('矢野', 0.7048444747924805)
('井口', 0.6532944440841675)
('名将', 0.6368062496185303)
('迷', 0.6259689331054688)
('采配', 0.6153334379196167)
"""

p_words, n_words = ['ホームラン'],[]
word2vec_model_check(model,p_words,n_words)

"""
# 実行結果
model.wv.most_similar(positive= ['ホームラン'] ,negative= [] )
('HR', 0.848455011844635)
('弾', 0.7043811082839966)
('アーチ', 0.6742182970046997)
('本塁打', 0.6652001142501831)
('ツーラン', 0.6070960760116577)
('ツーランホームラン', 0.5996525287628174)
('スリーランホームラン', 0.595179557800293)
('グラスラ', 0.5532823801040649)
('タイムリー', 0.4852123558521271)
('ヒット', 0.48372089862823486)
"""

```

「ラミレス」と「ホームラン」に近い単語TOP10を表示してみました。
「ラミレス」さんは監督なので，他のチームの監督の名前が上位になっています。
「ホームラン」は，別の表記方法などが上位になっています。



## ちくちく言葉・ふわふわ言葉の単語を定義

### 初期設定となる，ちくちく言葉・ふわふわ言葉の単語を指定

どのような単語をツイート内検索するのかを定めるために，検索ワードを２種類用意します。
chikuchiku_wordsとfuwa fuwa_wordsを以下のように設定。
（テキストデータとして載せたくなかったので，スクショで失礼します）
![スクリーンショット 2020-08-17 22.36.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597078/e1dfa5e0-ffa8-6435-74e8-c77a2094ae0f.png)


### Word2Vecを使って検索ワードを拡張
上記の単語だけだと，表記揺れや似たような表現があるはずなので，先ほど学習させたWord2Vecのモデルを用いて，検索ワードを拡張します。

初期の単語それぞれに対して，似た単語上位30件を抽出し，類似度が高い単語を検索ワードのリストに加えます。

```python
def get_related_words(model,search_words,thres,remove_words):
	related_words = []
	for sw in search_words:
		results = word2vec_model_check(model,sw,[])
		for r in results:
			if r[1]>thres:
				related_words.append(r[0])
	related_words = list(set(related_words+search_words)-set(remove_words))
	return related_words


# ちくちく言葉の単語リスト
search_words = chikuchiku_words
remove_words = [...省略] #抽出された単語でおかしいものを手動で削除
thres = 0.55 # 類似度の閾値
related_words = get_related_words(model,search_words,thres,remove_words)
print(related_words)

# ふわふわ言葉の単語リスト
search_words = fuwafuwa_words
remove_words = [...] #抽出された単語でおかしいものを手動で削除
thres = 0.55 # 類似度の閾値
related_words = get_related_words(model,search_words,thres,remove_words)
print(related_words)
```

結果，以下の言葉を「ちくちく言葉の単語リスト」「ふわふわ言葉の単語リスト」とします。
![スクリーンショット 2020-08-17 22.38.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597078/b6971572-c264-5830-4376-403dad1fcefe.png)



## ちくちく度・ふわふわ度の計算 

それぞれ，11球団のファンによる，ちくちく言葉（またはふわふわ言葉）が入っているツイート数とその割合を計算しました。

### ちくちく度

|     球団名   |     <font color="red">ちくちく言葉</font>を含むツイート数    |    ツイート総数    |ちくちく度|
|:----------------:|:------------------:|:------------------:|:------------------|
| 巨人             |8663|   590634       |1.47 %|
| 中日             |2776|  250771         |1.11 %|
| 広島             |7469|  442592         |<font color="red">1.69 %</font>|
| ヤクルト          |4992| 400029          |1.25 %|
| 阪神             |6217| 428525         |1.45 %|
| ＤｅＮＡ          |6468| 564144         | 1.14 %|
| 日本ハム	   |2846|   415629       |<font color="blue">0.685 %</font>|
| ソフトバンク       |3975|  487349         | 0.816 %|
| 楽天             |2548|  256291         | 0.994 %|
| 西武             |8163| 528261          |1.55 %|
| ロッテ            |4958| 395208         | 1.25 %|

うん，だいたい思った通りの結果。
<font color="red">●：「ちくちく度」</font>が一番高いのは広島，一番低いのは日ハムでした。


### ふわふわ度

|     球団名   |     <font color="blue">ふわふわ言葉</font>を含むツイート数    |    ツイート総数    |ふわふわ度|
|:----------------:|:------------------:|:------------------:|:------------------|
| 巨人             |20876|   590634       |3.53 %|
| 中日             |9989|  250771         |3.98 %|
| 広島             |21979|  442592         |4.97 %|
| ヤクルト          |22888| 400029          |5.72 %|
| 阪神             |13177| 428525         |<font color="red">3.07 %</font>|
| ＤｅＮＡ          |28083| 564144         | 4.98 %|
| 日本ハム	   |24105|   415629       |<font color="blue">5.80 %</font>|
| ソフトバンク       |26886|  487349         | 5.52 %|
| 楽天             |10877|  256291         | 4.24 %|
| 西武             |25462| 528261          |4.82 %|
| ロッテ            |15831| 395208         | 4.01 %|

ちくちく度のランキングとは少し違う様子。
<font color="blue">●：「ふわふわ度」</font>が一番高いのは日ハム，一番低いのは阪神でした。


### グラフにしてみた
<font color="red">◼︎ ちくちく度</font>，<font color="blue">◼︎ ふわふわ度</font>
![スクリーンショット 2020-08-19 4.27.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597078/4db458ad-010a-49b2-bb90-40dc18a3c78b.png)

> 心の声（おい，阪神ファンの人たちもっと選手を褒めてやれよ！ツンデレか？？）


# 考察

民度が低い投稿（<font color="red">ちくちく度</font>）は，おおよそどの球団も1%前後ということがわかりました。

検索ワードの検討で，検索ワード（ちくちく言葉，ふわふわ言葉）を少し変えたりして実験してみはしましたが，大きく結果が変わることはありませんでした。
有意差の計算はしていないので，意味のある差かどうかはわかりませんでしたが，おおよそ予想どうりになったと思います。

## 勝率との関係性

勝率をx軸として，<font color="red">「ちくちく度」</font><font color="blue">「ふわふわ度」</font><font color="green">「ふわふわ度/ちくちく度」</font>をプロットしてみた。（勝率は以下のデータから　[2019年度 公式戦成績](https://npb.jp/bis/2019/stats/ "2019年度 公式戦成績")）
点線は値の平均です。

<font color="green">「ふわふわ度/ちくちく度」</font>は，この値が高いほど，ちくちく言葉が少なく，ふわふわ言葉が多いということになります。
（ふわふわ度のばらつきが大きいので，ふわふわ度にかなり左右される値かもしれませんが）

<font color="red">●：「ちくちく度」</font>，<font color="blue">●：「ふわふわ度」</font>
<font color="green">●：「ふわふわ度/ちくちく度」</font>
![勝率との関係.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597078/091d2edc-041e-c1af-cb2a-2c0a02959112.png)

見事に相関がない。
つまりファンの民度依存の結果ということなのでしょうか，やっぱり。
でも，時期で分けてチームごとの変動を計算すれば，もしかしたら相関が現れるかもしれません。（ホンマか？）



## 「ちくちく度」「ふわふわ度」の関係
11球団の平均と比べたときに，球団の特徴が４つに分類できます。

ちくちく<font color="red">多</font>・ふわふわ<font color="red">少</font> ➡︎ 巨人・阪神・ロッテ
ちくちく<font color="red">多</font>・ふわふわ<font color="blue">多</font> ➡︎ 広島・西武・ヤクルト
ちくちく<font color="blue">少</font>・ふわふわ<font color="red">少</font> ➡︎ 中日・楽天
ちくちく<font color="blue">少</font>・ふわふわ<font color="blue">多</font> ➡︎ 日ハム・DeNA・ソフトバンク

> 上の方が民度が低めってことでいいんだろうか🤔🤔🤔




# まとめ

ツイッターに概要をかきました
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">プロ野球の実況ツイートからファンの民度を測ってみた <a href="https://t.co/kqUciEzsBD">https://t.co/kqUciEzsBD</a> <a href="https://twitter.com/hashtag/Qiita?src=hash&amp;ref_src=twsrc%5Etfw">#Qiita</a> <br><br>投稿しました！ <a href="https://twitter.com/hashtag/npb?src=hash&amp;ref_src=twsrc%5Etfw">#npb</a> <a href="https://twitter.com/hashtag/Qiita?src=hash&amp;ref_src=twsrc%5Etfw">#Qiita</a> <a href="https://t.co/SpNGQCExjV">pic.twitter.com/SpNGQCExjV</a></p>&mdash; のんのさん🟣 (@p_lab_n) <a href="https://twitter.com/p_lab_n/status/1295719323936460802?ref_src=twsrc%5Etfw">August 18, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
今回の分析だけでは，一概にどの球団のファンの民度が低いということは言えないですけど，
だいたい，多くの人が思っているような結果になったんではないでしょうか。

とにかく言えることは，
割合として「ちくちく度」<「ふわふわ度」になったのは本当に良かった😌
あと，日ハムのファンの方たち素晴らしい👏👏👏

> なんかもうちょっと考察が言える方がいらっしゃったら，コメントください。