#はじめに
この記事内で行っていることは、Twitter APIを用いてTwitter userのツイートを取得したツイートデータを用いて何かできないかと仮作したものです。
投稿時間遷移と感情遷移の作成プログラムは作成時期が異なるため、別物と考えてもらえると助かります。
ML-Askについて詳しい説明を行っている@yukino氏の記事を見てもらえると助かります。
ML-Askでテキストの感情分析
https://qiita.com/yukinoi/items/ef6fb48b5e3694e9659c
#プログラムを実行する前に行う事
今回のプログラムはTwitter APIを用いて取得したデータが必要です。
以下の様なデータが入っているcsvファイルであれば可能のはず...?
created_at | full_text |
---|---|
2018/4/10 15:22:06 | 笹かま食べたい |
#実行環境
Python 3.6.3 :: Anaconda custom (64-bit)
pandas 0.24.2
matplotlib 2.2.2
##1.時間遷移
まずは時間によってツイートの投稿が変化するのか見ていきたいと思います。
プログラムは以下の通りです。
import pandas as pd
import matplotlib.pyplot as plt
FILENAME_R ='任意のパス'
twitter_df = pd.read_csv(FILENAME_R,index_col=None, header=0,encoding="utf_8_sig")
twitter_df['created_at'] = pd.to_datetime(twitter_df['created_at'])
#日付のみ抽出
df_time_date = twitter_df['created_at'].dt.date
day_list = []
for date in df_time_date:
day_list.append(date.weekday())
#カウント
df_day = pd.DataFrame(day_list,columns=["Day"])
group_day = df_day['Day'].groupby(df_day['Day'])
cd = group_day.count()
cd.plot()
plt.xticks((0, 1, 2, 3, 4, 5, 6, 7), ('月曜日','火曜日','水曜日','木曜日','金曜日','土曜日','日曜日'))
土曜日が少ないというちょっと面白い結果になりました。
但し、金曜日、日曜日が最高潮に達するのはなんとなくわかりますね!
※ちなみにこれは私が持っているデータのみの結果です。一概にはこの通りとなるとは言えません。
※別のデータで行った場合、日曜日土曜日が多く、火曜日が一番少ないという結果になりました。
また、プログラム中の抽出部分とカウント部分を以下の様に変更し実行すると...
#時間のみ抽出
df_time = twitter_df['created_at'].dt.hour
time_group = df_time.groupby(df_time)
#カウント
twitter_user_time_count = time_group.count()
twitter_user_time_count.plot()
12時の昼休み頃にツイートが突起の様に増え
23,24時等の寝る前になるとツイートをする人が最高潮になるという面白い結果が出ましたね!
##2.感情遷移
感情分析に使用するMLAskですが、analyzeに渡すと辞書型で返ってきます。
その中で 'emotion'と'representative'がありますが、
今回のプログラムでは'representative'を使用します。
以下プログラムです。
import re
from mlask import MLAsk
emotion_analyzer = MLAsk()
import pandas as pd
import matplotlib.pyplot as plt
#rep
def emotion_mlask_rep(sentence): #str -> dict
emotion_dict = emotion_analyzer.analyze(sentence)
if emotion_dict['emotion']:
emotion,text = emotion_dict['representative'] #tuple(str,list[str]) -> str,list
return {emotion:len(text),'full_text':sentence}
else:
return {'None':1,'full_text':sentence}
#前処理
pattern1 = re.compile(r'RT') #排除
pattern2= re.compile(r"@([A-Za-z0-9_]+)")#排除
pattern3 = re.compile(r'(https?|ftp)(:\/\/[-_\.!~*\'()a-zA-Z0-9;\/?:\@&=\+\$,%#]+)')#排除
pattern4 = re.compile(r'#(\w+)')#削除
def re_def(sentence_list): #list -> list
subsentence_list = []
for sentence in sentence_list:
sub4 = re.sub(pattern4,"",sentence)
if (re.search(pattern1,sentence) or re.search(pattern2,sentence) or re.search(pattern3,sentence)) == None:
subsentence_list.append(sub4)
return subsentence_list
前処理として以下のものを行っています。
1.リツイート、メンション、URLの含むデータの排除
2.ハッシュタグが含まれるツイートはハッシュタグ部のみ削除
#csv読み込み
FILENAME_R="読み込むデータのある場所への任意のパス"
twitter_df = pd.read_csv(FILENAME_R,index_col=None,usecols=["created_at","full_text"], header=0,encoding="utf_8_sig")
#テキストリスト化
twitter_df_text_list = twitter_df['full_text'].values.tolist()
twitter_df['created_at'] = pd.to_datetime(twitter_df['created_at'])
emotion_df = pd.DataFrame(index=None,columns=['full_text','yorokobi','ikari','aware','kowa',
'haji','suki','iya','takaburi',
'yasu','odoroki','None'])
tmp_list = []
for sentence in twitter_df_text_list:
emotion_dict = emotion_mlask_rep(sentence) #str → dict
tmp_list.append(emotion_dict)
emotion_df = pd.concat([emotion_df, pd.DataFrame.from_dict(tmp_list)])
twitter_df = pd.merge(twitter_df,emotion_df)
tmp_listはlist型ですが、中に複数の辞書を入ってます。
emotion_df = pd.concat([emotion_df, pd.DataFrame.from_dict(tmp_list)])
この部分でemotion_dfにtmp_listに入れた辞書データを連結させています。
(最初に、emotion_dfを空のデータフレームとして宣言した理由です。)
twitter_df_nan2zero = twitter_df.fillna(0)
twitter_df_nan2zero = twitter_df_nan2zero.drop(['full_text'],axis=1)
#Noneが1である行を除外
twitter_df_subNone = twitter_df_nan2zero[twitter_df_nan2zero['None'] != 1]
twitter_df_subNone = twitter_df_subNone.drop(['None'],axis=1)
twitter_df_subNone.set_index('created_at')
後々、pandasのgroupeby.sum()を使用するため、Nanを0に置き換えます。
また、ML-AskとTwitterの文章の特性上判定から漏れる(Noneと判定される)ものは排除しています。
##time emotion transition on twitter
df_time = twitter_df_subNone['created_at'].dt.hour
twitter_df_subNone['created_at'] = df_time.values
time_group=twitter_df_subNone.groupby('created_at').sum()
twitter_user_time_count = time_group.count()
#各感情の各合計値とその時間での感情値を割る
time_group_per_sum = time_group/time_group.sum()
time_group_per_sum.plot()
plt.savefig('任意の名前')
嫌という感情が21時ごろから減るのは少し面白いですね!
#終わりに
今回使用したデータのそれぞれの判定された感情の合計値は以下の通りです。
Noneに判定されたものが多く、時点で嫌,喜びといった感情になっています。
感情分類からこぼれたデータが多くもったいないので、機械学習による感情分析に移行したほうが良いのでは?とも思いました。
また左軸感情、右軸ツイートの回数、横軸 曜日etc... にすれば分かりやすかったなと少し思います。
※後々の改善点として表記