【技術編】『ラジカツスターズ!』全102回とコーナー全364問から見えてくるもの
先週書いた『ラジカツスターズ!』の分析で使用したpytonコードをメモとして記載しておく。 snofra.hatenablog.com
実装
ロード部
import pandas as pd import matplotlib.pyplot as plt import statsmodels.api as sm import numpy as np import datetime %pylab inline --no-import-all #csvファイルのロード df = pd.read_csv('C:/Users/xxxx/radikatsu_stars_list.csv', index_col=0, parse_dates=[1], engine='python') df = df.fillna(0) radikatsu = df.loc[0:] # todo 正解数の抽出できなかったので加工
データ加工部
on_air = radikatsu.index # 放送回数 series_correct_num = radikatsu['正解数'].astype(int) # 正解数全量 series_question_num = radikatsu['出題数'].astype(int) # 出題数全量 # 正解数と出題数をそれぞれ累計 list_cumulative_correct = [] # 正解数 list_cumulative_question = [] # 出題数 list_cumulative_correct_rate = [] # 正解率 cumulative_correct = 0 cumulative_question = 0 cumulative_correct_rate = 0 for x, y in zip(series_correct_num, series_question_num): cumulative_correct = cumulative_correct + x cumulative_question = cumulative_question + y # 暫く0が続くのでその場合は処理を行わない if x != 0 and y !=0: cumulative_correct_rate = (cumulative_correct / cumulative_question) * 100 list_cumulative_correct.append(cumulative_correct) # 正解数累計 list_cumulative_question.append(cumulative_question) # 問題数累計 list_cumulative_correct_rate.append(cumulative_correct_rate) # 正解率累計 # 各累計数をDataFrameにする cumulative = pd.DataFrame( {'01.on_air': on_air, '02.question': list_cumulative_question, '03.correct': list_cumulative_correct, '04.rate': list_cumulative_correct_rate}) print(cumulative) cumulative.to_csv("cumulative.csv")
こんな感じで出力
データ加工部(メンバー別)
def member_answer(member): #担当回チェック list_question = [] #問題数 list_correct = [] #正解数 list_date = [] #放送年月 list_cast = [] #パーソナリティ回数 bfr_date = None question_num = 0 answer_num = 0 cast_num = 0 len_cur = len(radikatsu) # DataFrameの行単位でループ for index, i in enumerate(radikatsu.iterrows()): # tupleの値部分の取得 series_row = i[1] target = series_row['公開日'].strftime("%Y-%m") # パーソナリティ回だった場合 if series_row[member] == 1: # 同年月だった場合累計 if target == bfr_date: question_num = question_num + series_row['出題数'] answer_num = answer_num + series_row['正解数'] cast_num = cast_num + 1 # 1行目もしくは年月が切り替わった場合 if target != bfr_date and bfr_date is not None: list_date.append(bfr_date) list_question.append(question_num) list_correct.append(answer_num) list_cast.append(cast_num) # パーソナリティ回だった場合、その年月を設定しなおす。 if series_row[member] == 1: question_num = series_row['出題数'] answer_num = series_row['正解数'] cast_num = 1 else: question_num = 0 answer_num = 0 cast_num = 0 bfr_date = target # 最終行の追加 if len_cur == index + 1: list_date.append(target) list_question.append(question_num) list_correct.append(answer_num) list_cast.append(cast_num) # 年月別の問題/回答数 member_correct = pd.DataFrame( {'01.year': list_date, '02.question': list_question, '03.correct': list_correct, '04.parsonarty': list_cast}) print(member_correct) member_correct.to_csv("member_correct" + member + ".csv") # 問題数/正解数/正解率の最大値の取得 question_crr = 0 answer_crr = 0 cast_crr = 0 for x, y, z in zip(list_question, list_correct, list_cast): question_crr = question_crr + x answer_crr = answer_crr + y cast_crr = cast_crr + z crr_ans_rate = (answer_crr / question_crr) * 100 # jupiterを日本語対応していないので、適当にタイトルを設定 if member == "るか": title = "Ruka's Question/Correct num" elif member == "みき": title = "Miki's Question/Correct num" elif member == "かな": title = "Kana's Question/Correct num" elif member == "みほ": title = "Miho's Question/Correct num" elif member == "ななせ": title = "Nanase's Question/Correct num" elif member == "せな": title = "Sena's Question/Correct num" else: title = "Rie's Question/Answer num" # X軸表示用に年月分連番を設定しておく serial_no = [index + 1 for index, i in enumerate(list_date)] # plot plt.figure(figsize=(20, 10), dpi=100, linewidth = 100) ax = plt.subplot() ax.bar(serial_no, list_question, color='#44A5CB', align="center", label="Question num") # 問題数 ax.bar(serial_no, list_correct, color='#EDAD0B', align="center", label="Correct num") # 正解数 plt.ylabel("Question/Correct num", fontsize=15) ax.legend(loc=2) # 凡例 plt.title(title, fontsize=15) plt.yticks( np.arange(0, 20, 1) ) plt.xticks(serial_no, list_date, rotation = 90) plt.savefig(member + '.png') # グラフのダウンロード plt.show() return question_crr, answer_crr, crr_ans_rate, cast_crr
メンバー別の表示
list_question_cum = [] list_answer_cum = [] list_crr_ans_rate = [] list_cast_cum =[] # るか question_ruka, answer_ruka, rate_ruka, cast_ruka = member_answer('るか') list_question_cum.append(question_ruka) list_answer_cum.append(answer_ruka) list_crr_ans_rate.append(rate_ruka) list_cast_cum.append(cast_ruka) # みき question_miki, answer_miki, rate_miki, cast_miki = member_answer('みき') list_question_cum.append(question_miki) list_answer_cum.append(answer_miki) list_crr_ans_rate.append(rate_miki) list_cast_cum.append(cast_miki) # かな question_kana, answer_kana, rate_kana, cast_kana = member_answer('かな') list_question_cum.append(question_kana) list_answer_cum.append(answer_kana) list_crr_ans_rate.append(rate_kana) list_cast_cum.append(cast_kana) # みほ question_miho, answer_miho, rate_miho, cast_miho = member_answer('みほ') list_question_cum.append(question_miho) list_answer_cum.append(answer_miho) list_crr_ans_rate.append(rate_miho) list_cast_cum.append(cast_miho) # ななせ question_nanase, answer_nanase, rate_nanase, cast_nanase = member_answer('ななせ') list_question_cum.append(question_nanase) list_answer_cum.append(answer_nanase) list_crr_ans_rate.append(rate_nanase) list_cast_cum.append(cast_nanase) # せな question_sena, answer_sena, rate_sena, cast_sena = member_answer('せな') list_question_cum.append(question_sena) list_answer_cum.append(answer_sena) list_crr_ans_rate.append(rate_sena) list_cast_cum.append(cast_sena) # りえ question_rie, answer_rie, rate_rie, cast_rie = member_answer('りえ') list_question_cum.append(question_rie) list_answer_cum.append(answer_rie) list_crr_ans_rate.append(rate_rie) list_cast_cum.append(cast_rie) # メンバー別の問題数/正解数/正解率 crr_ans_rate = pd.DataFrame( {'01.member': ['るか', 'みき', 'かな', 'みほ', 'ななせ', 'せな', 'りえ'], '02.question': list_question_cum, '03.answer': list_answer_cum, '04.correct_rate': list_crr_ans_rate, '05.parsonaroty': list_cast_cum }) print(crr_ans_rate) crr_ans_rate.to_csv("crr_ans_rate.csv")
メンバー別、月別で問題数と正解数を作ったんだけど。分析するにはいまいち言うこともないし、微妙じゃね?ということで結局載せなかった。
せなとみほの正解数推移比較
# せな list_sena = [] # DataFrameの行単位でループ for index, i in enumerate(radikatsu.iterrows()): # tupleの値部分の取得 series_row = i[1] target = series_row['公開日'].strftime("%Y-%m") # パーソナリティ回だった場合 if series_row['せな'] == 1: list_sena.append(series_row['正解数']) # みほ list_miho = [] # DataFrameの行単位でループ for index, i in enumerate(radikatsu.iterrows()): # tupleの値部分の取得 series_row = i[1] target = series_row['公開日'].strftime("%Y-%m") # パーソナリティ回だった場合 if series_row['みほ'] == 1: list_miho.append(series_row['正解数']) # seabornでせなとみほの結果をカーネル密度推計でplot import matplotlib.pyplot as plt import seaborn as sns plt.figure(figsize=(20, 10), dpi=100, linewidth = 100) plt.xticks([0,1,2,3,4,5]) plt.tick_params(labelsize=18) plt.xlabel('Answer', fontsize=18) sns.distplot(pd.DataFrame({'sena':list_sena}), rug=True, hist=False, color = 'pink', kde_kws={'label':'sena'}) sns.distplot(pd.DataFrame({'sena':list_miho}), rug=True, hist=False, color = 'purple', kde_kws={'label':'miho'}) plt.legend(fontsize=18) plt.savefig('sena_vs_miho.png')
できた画像を多少加工しているけど、こんな感じのグラフができる。
みほ、せなコンビで今度ライブをやるとのことで、ラジカツ優秀勢きたなって思いました(小並感)
『天音みほ(@miiii_am)』と『堀越せな(@sena_horysan)』によるSpecialライブを開催✨春ということで新しい出逢いがあるかも⁉
— DEARSTAGE inc. (@DEARSTAGE_inc) 2018年4月5日
📆4/22(日)18:45開場/19:15開演
🚪TwinBox AKIHABARA
🎫スタンディング4320円
今週末4/7(土)10:00~Twitter先行抽選受付開始📢申込URLは後日お知らせします💻お見逃しなく💨 pic.twitter.com/tero63TmFH
メンバー別の表示
# メンバー別質問数と正解数、正解率 appr_member = [1,2,3,4,5,6,7] # X軸の表示用 # plot plt.figure(figsize=(20, 10), dpi=100, linewidth = 100) ax = plt.subplot() ax.bar(appr_member, list_question_cum, color='#44A5CB', align="center", label="Question num") # 問題数 ax.bar(appr_member, list_answer_cum, color='#EDAD0B', align="center", label="Correct num") # 正解数 ax.legend(loc=2) # 凡例 plt.yticks( np.arange(0, max(list_question_cum)+3, 10) ) plt.xticks(appr_member, ['ruka', 'miki', 'kana', 'miho', 'nanase', 'sena', 'rie'], rotation = 90, fontsize=15) plt.ylabel("Question num", fontsize=15) ax2 = ax.twinx() ax2.plot(appr_member, list_crr_ans_rate, linewidth=5, marker='o', markersize=10, color='#C7243A') # 正解率 plt.ylabel("Correct answer rate", fontsize=15) plt.savefig('Correct answer rate.png') # グラフのダウンロード plt.show()
すでに用意していたのをベースに作業していたんだけど、ここはmatplotlibよりもbokehにしようと思ってた。
だけど、bokehだとグラフを複数使用したときのY軸が左右にでなくて、右のY軸にメモリなきゃ雰囲気グラフやんと思って、結局matplotlibのままでいくことにした。
ちなみにこんなグラフが出る。
番組への貢献度表示
# 番組への貢献度をbokehでプロット from bokeh.plotting import figure, output_file, show from bokeh.io import output_notebook from bokeh.models import ColumnDataSource, LabelSet, Range1d output_notebook() source = ColumnDataSource(data=dict(ans=list_crr_ans_rate, cast=list_cast_cum, names=['るか', 'みき', 'かな', 'みほ', 'ななせ', 'せな', 'りえ'], colors=['orange', 'green', '#ef5285', 'purple', 'blue', 'pink', '#00b9f1'])) p = figure(title = "誰が番組に貢献したか", x_range=Range1d(30, 40),y_range=Range1d(10, 40)) p.xaxis[0].axis_label = 'パーソナリティ回数' p.yaxis[0].axis_label = '正解率(%)' p.scatter(x='cast', y='ans', size=8, source=source, color='colors') labels = LabelSet(x='cast', y='ans', text='names', level='glyph', x_offset=5, y_offset=5, source=source, render_mode='canvas') p.add_layout(labels) show(p)
こんな感じのグラフが出る。
matplotlibとどう違うんだってのも見てみたけど、実装の楽さや見栄え見てもbokehがいいね。
matplotlibはDataFrame使えないし、色をこまめに変えたい場合実装行数が多くなるのが難点。
matplotlibでの散布図実装
お試しでやってみたので併せて載せておく。
# dataFrameの作成 cumulative = pd.DataFrame( {'names': ['るか', 'みき', 'かな', 'みほ', 'ななせ', 'せな', 'りえ'], 'ans': list_crr_ans_rate, 'cast': list_cast_cum, 'colors': ['orange', 'green', '#ef5285', 'purple', 'blue', 'pink', '#00b9f1']}) # メンバー別にパージしておく ruka = cumulative[0:1] miki = cumulative[1:2] kana = cumulative[2:3] miho= cumulative[3:4] nanase = cumulative[4:5] sena = cumulative[5:6] rie = cumulative[6:7] # plot fig = plt.figure() ax = fig.add_subplot(1,1,1) ax.scatter(ruka["cast"], ruka["ans"], c=ruka["colors"]) ax.annotate("ruka",xy=(ruka["cast"], ruka["ans"]),size=10) ax.scatter(miki["cast"], miki["ans"], c=miki["colors"]) ax.annotate("miki",xy=(miki["cast"], miki["ans"]),size=10) ax.scatter(kana["cast"], kana["ans"], c=kana["colors"]) ax.annotate("kana",xy=(kana["cast"], kana["ans"]),size=10) ax.scatter(miho["cast"], miho["ans"], c=miho["colors"]) ax.annotate("miho",xy=(miho["cast"], miho["ans"]),size=10) ax.scatter(nanase["cast"], nanase["ans"], c=nanase["colors"]) ax.annotate("nanase",xy=(nanase["cast"], nanase["ans"]),size=10) ax.scatter(sena["cast"], sena["ans"], c=sena["colors"]) ax.annotate("sena",xy=(sena["cast"], sena["ans"]),size=10) ax.scatter(rie["cast"], rie["ans"], c=rie["colors"]) ax.annotate("rie",xy=(rie["cast"], rie["ans"]),size=10) ax.set_xlabel('parsonality num') ax.set_ylabel('correct per') plt.savefig('matplotlib.png') # グラフのダウンロード plt.show()
これだったらbokehでいいかなー