見出し画像

ワクチンに関するつぶやきを可視化してみる

新型コロナウイルスワクチンに限らず、予防医学の観点からワクチン接種はとても重要です。
日本において、ワクチン接種の重要性がこれほど強調されたことはかつてなく、日本人の意識や行動に大なり小なり影響を及ぼしていると考えられます。
みなさんがワクチンに対してどのような思いを抱いているのか描き出したいという動機から、Twitterのツイート情報を利用してワクチンに関連する単語の可視化を試みることとしました。

開発環境

  • OS : macOS version11.4

  • Python 3.7.12

  • Pythonの実行環境 : Google Colaboratory

手順

ワクチンに関するTwitterのツイートの可視化は、次のような手順で行いました。

  1. Twitter APIの取得

  2. ワクチンに関するツイートの取得

  3. 形態素解析

  4. 可視化

手順に沿って解説したいと思います。

Twitter APIの取得

Twitter のツイートを取得するためにはAPIの利用申請が必要となります。
申請方法は以下のURLを参照しました。

無料でデータを得られるアクセスレベルに"Essential"と"Elevated"の2種類があり、取得できるツイートの数が異なります。当初、多くのツイートを取得する予定であったため、"Elevated"の申請を行いましたが、結果的には必要ありませんでした。

ワクチンに関するツイートの収集

「ワクチン」を検索語として、「ワクチン」という単語を含むツイートを取得することとしました。APIの制限から、収集するツイートは、収集時点(2021/3/9)から遡って1週間以内にツイートされた25,000件としました。

ライブラリは以下のものを使用しました。
Tweepyはツイートを取得するために用いたライブラリになります。

!pip install git+https://github.com/tweepy/tweepy.git
import pandas as pd
import tweepy
import csv

まず、クライアント関数を作成しました。

# API情報を記入
BEARER_TOKEN = "*******"
API_KEY = "*******"
API_SECRET = "*******"
ACCESS_TOKEN = "******"*
ACCESS_TOKEN_SECRET = "*******"
#クライアント関数を作成
client = tweepy.Client(bearer_token    = BEARER_TOKEN,
                           consumer_key    = API_KEY,
                           consumer_secret = API_SECRET,
                           access_token    = ACCESS_TOKEN,
                           access_token_secret = ACCESS_TOKEN_SECRET,
                          )

続いて、ツイートを取得するコードを実行しました。
リツイートを除いて「ワクチン」を含むツイートを25,000件収集し、「tweets_vaccine.csv」のCSVファイルに保存しました。

# 検索語
query = 'ワクチン -is:retweet'
# 保存するCSVファイルの名前
file_name = 'tweets_vaccine.csv'

with open(file_name,mode="w",encoding="utf-8") as f:
            writer=csv.writer(f)
            header=[
                "tweet_id",
                "post_date",
                "text"
                ]
            writer.writerow(header)

for tweet in tweepy.Paginator(client.search_recent_tweets,
                              query=query, 
                              tweet_fields = ["created_at", "text", "source", "context_annotations"],
                              user_fields = ["username", "location", "verified", "description"],
                              max_results = 100).flatten(limit=25000): # ツイート件数は25,000
                              with open(file_name,mode="a",encoding="utf-8") as f:
                                writer=csv.writer(f)
                                body=[
                                      tweet.id,
                                      tweet.created_at,
                                      tweet.text
                                      ]
                                writer.writerow(body)

取得したツイートの結果は以下の通りです。

df = pd.read_csv("tweets_vaccine.csv")
df

形態素解析

収集したツイートを基に形態素解析を行いました。
形態素解析についての解説は、こちらのnoteが分かりやすかったです。

まず、ツイートの正規化を実施しました。
正規化は、半角を全角にしたり、大文字のアルファベットを小文字にしたり、単語の表現のゆらぎを統一したり、処理しやすいように表現を整えます。
また、可視化の際にノイズとなるため、URL、メンションを削除する処理も実施しました。

#テキストの正規化
!pip install neologdn
import neologdn
n_texts = []
for i in df['text']:
  n_text = neologdn.normalize(i)
  # URLを削除
  result = re.sub("https?://[\w!\?/\+\-_~=;\.,\*&@#\$%\(\)'\[\]]+", "", n_text)
  # メンションを削除
  result = re.sub("@[\\w]{1,15}", "", result)
  n_texts.append(result)
df["n_text"] = n_texts
df.head()
正規化後

前処理が完了したデータを用いて形態素解析を実施しました。形態素解析のコードはこちらを参照しました。
https://boxcode.jp/pythonで感情分析(形態素解析準備編)-mecab

# 形態素分析ライブラリーMeCab と 辞書(mecab-ipadic-NEologd)のインストール 
!apt-get -q -y install sudo file mecab libmecab-dev mecab-ipadic-utf8 git curl python-mecab > /dev/null
!git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git > /dev/null 
!echo yes | mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n > /dev/null 2>&1
!pip install mecab-python3 > /dev/null
import MeCab
import re

# シンボリックリンクによるエラー回避
!ln -s /etc/mecabrc /usr/local/etc/mecabrc

def mecab_text(text):
    
  # 辞書はmecab-ipadic-neologdを使用
  path = "-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd"
  mecab = MeCab.Tagger(path)
  
  #形態素解析
  node = mecab.parseToNode(text)
  
  #形態素解析した結果を格納するリスト
  wordlist = []
  
  while node:
      #名詞のみリストに格納する
      if node.feature.split(',')[0] == '名詞':
          wordlist.append(node.surface)
      node = node.next
  return wordlist
#形態素結果をリスト化し、データフレームdfに結果を列追加する
df['words'] = df['n_text'].apply(mecab_text)
df.head()

可視化

可視化にはnlplotというライブラリを使用しました。

# nlplotをインストール
!pip install nlplot
import nlplot

npt = nlplot.NLPlot(df, target_col='words')

今回、最頻出単語として「ワクチン」が表示されないように、上位1位の単語をストップワードに設定しました。

# ストップワードの設定
# top_nで頻出上位単語, min_freqで頻出下位単語を指定できる
stopwords = npt.get_stopword(top_n=1, min_freq=0) 

単語別に出現頻度を棒グラフで表します。

 npt.bar_ngram(
    title='uni-gram',
    xaxis_label='word_count',
    yaxis_label='word',
    ngram=1,
    top_n=50,
    stopwords=stopwords,
)

2単語の出現頻度は以下のようになります。

 npt.bar_ngram(
    title='uni-gram',
    xaxis_label='word_count',
    yaxis_label='word',
    ngram=2,
    top_n=50,
    stopwords=stopwords,
)

Wordcloudです。

npt.wordcloud(
    max_words=50,
    max_font_size=100,
    colormap='tab20_r',
    stopwords=stopwords,
) 

共起ネットワークです。

npt.build_graph(stopwords=stopwords, min_edge_frequency=110)
npt.co_network(
    title='Co-occurrence network',
) 

考察

今回、ワクチンと関連した単語をツイートから抽出し可視化してみました。
「接種」や「3回目」、「今日」という単語が出現頻度の上位に位置しており、3回目接種が終了したことを報告するツイートが多かったと推測されます。そうであれば、接種が進んでいる状況を示しており、感染予防の観点から喜ばしい状態といえるかと思います。
接種を報告するツイートが多く流れることによりある種の規範が形成され、ワクチン接種行動に影響を及ぼした可能性があるかもしれません。
副反応を想起させる単語も散見されており、副反応への不安が見て取れます。
また、関連単語の中には、一見、ワクチンと関連性がないような単語が見受けられれます。これらは調べてみるとデマ情報に関連した単語であることが分かりました(デマを再拡散することになりかねないため、ここでは具体的な言及を避けます)。ワクチンに対する不安感・不信感の現れと捉えることができ、ワクチンに関する正しい情報を丁寧に説明していく必要性を感じました。
技術的な点については、上位にひらがな一文字や指示語など、意味を持たない単語が含まれており、ノイズ除去の難しさを感じました。
また、今回は単語の可視化まででしたが、感情分析にまで発展させてより精緻な分析を実施したいと思いました。

いいなと思ったら応援しよう!