はじめに
今まで動画の再生回数や高評価をプロットしてきたが,これらを使って勝手に動画のスコアを定義してランキング化したい欲が急に出てきたので,公式も含め誰かにされる前に記事を作成してみた.今回は正規化なる手法を用いてみる.
今まで書いた記事はこちら↓↓
- 「全力回避フラグちゃん!」チャンネルの動画をグラフ化するとどうなるのか?【Python】【グラフ化】
- 全力回避フラグちゃん! の動画再生数の分布を調べてみた【Python】【グラフ化】
- 全力回避フラグちゃん!の動画の再生数と評価/コメント数をグラフにしたらどうなるのか?【Python】【グラフ化】
- 全力回避フラグちゃん!で少しわかるYouTube Data API Channels リソースから取得できる主な情報
- 全力回避フラグちゃん!のチャンネルの人気は本当にほぼフラグちゃんで成り立っているのか?【検証】【可視化】
注意事項
2021/1/13 18:30時点で取得した情報を利用しています.
ランキングはあくまでも用いたデータの中でのランキングです.
異論は存在します.
用いたデータセット/手法
YouTube Data API のVideos リソースを使用し,2021/1/13 18:30時点において,全力回避フラグちゃん! のチャンネルにアップロードされている全227本の動画再生回数と高評価数を取得し,それらの数値を用いてスコアリングをします.
スコアリングする際に,再生回数と高評価数を最小値0,最大値1の範囲で正規化を実施します.
ちなみに,データセットをグラフ化したものは以下の図になります.
あとで再生回数と高評価数が多い動画をリストアップします.このグラフで山になっている部分がリストアップされると思ってください.
数値の正規化
今回は、再生回数と高評価の2つのデータを使用します.しかし,再生回数と高評価の最大値,最小値,平均値,中央値は以下のようになっており,これらの数値をそのまま使用したのではいくら高評価が高くても,再生回数がその差を吸収してしまい,高評価を用いる意味が薄れてしまいます.1
データ | 最大値 | 最小値 | 平均値 | 中央値 |
---|---|---|---|---|
再生回数 | 3,279,627 | 8,568 | 784,836 | 650,006 |
高評価 | 28,272 | 1,069 | 8,509 | 7,524 |
そこで,双方の値を最小値は0,最大値は1とするよう正規化を実施することで値の差による影響を吸収します.2
再生回数と高評価を正規化した値同士を掛け合わせ,最後に100をかけたものを動画に対するスコアと定義します.
どちらの値も最小値が0,最大値は1なので,掛け合わせた数値も最小値は0,最大値は1となります.すなわち,スコアの値域は0~100となり,これで100点満点で動画をスコアリングできます.
ある動画$i$の再生回数は$v_i$,高評価数は$l_i$,それぞれの値の正規化を$v_{n_i}, l_{n_i}$とすると,その動画のスコア$S_i$は,
$$ S_i = v_{n_i} \times l_{n_i} \times 100, \ 0 \leq S_i \leq 100.$$
ただし,
$$v_{n_i} = \frac{v_i - v_{min}}{v_{max} - v_{min}}, \ 0 \leq v_{n_i} \leq 1$$
$$l_{n_i} = \frac{l_i - l_{min}}{l_{max} - l_{min}}, \ 0 \leq l_{n_i} \leq 1$$
です.ここで,添え字のmax, min はそれぞれの値の最大値,最小値を指しています.
また,$1 \leq i \leq N$であり,$N$は動画の本数で現時点で$N = 227$です.
候補となる動画
では,上記の式を用いて動画をスコアリングしていきます.その前にまずは上位に位置付けられそうな動画たちをピックアップします.
以下の表は,2021/1/13 18:30 時点での再生回数のトップ10の動画のタイトルと,その再生回数,高評価数です.
順位 (再生回数) | タイトル | 再生回数 | 高評価数 | 順位 (高評価数) |
---|---|---|---|---|
1 | 【無痛症】痛みを感じなくなった男の末路…【アニメ】【漫画動画】 | 3,279,627 | 28,272 | 1 |
2 | 【アニメ】整形中毒になるとどうなるのか…生まれ変われるってホント!?【漫画動画】 | 3,267,978 | 21,745 | 4 |
3 | 【漫画】もしも小人になったらどうなるのか?…あんなコトやこんなコトが…??【アニメ】【漫画動画】 | 2,964,358 | 26,078 | 2 |
4 | 5億年ボタンを押したらどうなるのか?【アニメ】【漫画動画】 | 2,256,964 | 18,486 | 6 |
5 | 【アニメ】冗談で告白した相手から恐怖の手紙が…→意外な真実が【漫画動画】 | 2,141,762 | 16,364 | 11 |
6 | 混浴風呂で知り合いと出会うとどうなるのか?【アニメ】【漫画動画】 | 1,978,827 | 18,107 | 7 |
7 | 服が透けて見えるメガネを手にした男の夢ある行動とは…【アニメ】【漫画動画】 | 1,932,898 | 14,076 | 17 |
8 | 【漫画】お風呂で寝ると失神する!?お風呂に入るうえで注意した方が良いこと【アニメ】【漫画動画】 | 1,892,814 | 15,558 | 12 |
9 | もし性別が入れ替わったらどうなるのか?【アニメ】【漫画動画】 | 1,795,945 | 15,390 | 14 |
10 | 【漫画】糖尿病の本当の恐怖…あなたは大丈夫…?【アニメ】【漫画動画】 | 1,788,351 | 13,947 | 18 |
過去の動画が多く,最近の動画はないですね.やはり,再生回数は時間の積み重ねということでしょうか.
次に,2021/1/13 18:30 時点での高評価数のトップ10の動画のタイトルと,その再生回数,高評価数です.
順位 (高評価数) | タイトル | 再生回数 | 高評価数 | 順位 (再生回数) |
---|---|---|---|---|
1 | 【無痛症】痛みを感じなくなった男の末路…【アニメ】【漫画動画】 | 3,279,627 | 28,272 | 1 |
2 | 【漫画】もしも小人になったらどうなるのか?…あんなコトやこんなコトが…??【アニメ】【漫画動画】 | 2,964,358 | 26,078 | 3 |
3 | 死亡フラグの1DAYルーティン【アニメ】【漫画動画】 | 925,564 | 21,923 | 68 |
4 | 【アニメ】整形中毒になるとどうなるのか…生まれ変われるってホント!?【漫画動画】 | 3,267,978 | 21,745 | 2 |
5 | 【究極の選択】金と人の命はどちらが大事なのか…?【アニメ】【漫画動画】 | 393,835 | 21,713 | 194 |
6 | 5億年ボタンを押したらどうなるのか?【アニメ】【漫画動画】 | 2,256,964 | 18,486 | 4 |
7 | 混浴風呂で知り合いと出会うとどうなるのか?【アニメ】【漫画動画】 | 1,978,827 | 18,107 | 6 |
8 | 【ストーリー編】第1話「修行のはじまり」【アニメ】【漫画動画】 | 1,505,448 | 17,433 | 18 |
9 | 【新キャラ】ガンになるとどうなるのか…最強のフラグが!?【漫画動画】 | 1,580,870 | 16,936 | 15 |
10 | 首都直下地震が起きたらどうなるのか【アニメ】【漫画動画】 | 1,655,101 | 16,901 | 12 |
こちらには,最近公開された動画もちらほらあります.再生回数の面で不利になりますが,どこまで高いスコアがつけられるか...
上記の表の中にある動画から,本記事のスコアリングによるトップ10の動画が出るはずです.
ランキング結果
それでは,上記スコアリングによるランキング結果です.
トップ10を表にしました.スコアは,小数点以下第二位まで有効数字です.
|順位 (スコア)|タイトル |スコア|再生回数 | 高評価数|
|:-:|---|:-:|:-:|:-:|:-:|
|1| 【無痛症】痛みを感じなくなった男の末路…【アニメ】【漫画動画】 |100.00| 3,279,627 | 28,272|
|2|【漫画】もしも小人になったらどうなるのか?…あんなコトやこんなコトが…??【アニメ】【漫画動画】 | 83.31|2,964,358 |26,078|
|3| 【アニメ】整形中毒になるとどうなるのか…生まれ変われるってホント!?【漫画動画】|75.74 |3,267,978|21,745|
|4|5億年ボタンを押したらどうなるのか?【アニメ】【漫画動画】|44.01|2,256,964|18,486|
|5|混浴風呂で知り合いと出会うとどうなるのか?【アニメ】【漫画動画】|37.73|1,978,827|18,107|6|
|6|【アニメ】冗談で告白した相手から恐怖の手紙が…→意外な真実が【漫画動画】|36.67|2,141,762|16,364|
|7|【漫画】お風呂で寝ると失神する!?お風呂に入るうえで注意した方が良いこと【アニメ】【漫画動画】|30.68|1,892,814|15,558|
|8|首都直下地震が起きたらどうなるのか【アニメ】【漫画動画】|29.30|1,655,101|16,901|
|9|もし性別が入れ替わったらどうなるのか?【アニメ】【漫画動画】|28.77|1,795,945|15,390|
|10|服が透けて見えるメガネを手にした男の夢ある行動とは…【アニメ】【漫画動画】|28.13|1,932,898|14,076|
思ったよりもスコアが低くなってしまった.式の定義が甘かったか...
ちなみに,スコアの平均値は8.71,中央値は4.76です.
上記のランキングに載っている動画たちは平均の3倍以上の数値は持っているので,再生回数も高評価数も十分高い人気動画であるといえます.もう少し高いスコアが出るように定義してやるべきだった...
簡単な解説
各動画を簡単に解説していきます.なお,著作権に配慮して動画のURLは載せますが,サムネイルは載せません.ご了承ください...3
→ はてなブログのほうに補完記事という意味合いで埋め込み使って紹介しています.
1位: 【無痛症】痛みを感じなくなった男の末路…【アニメ】【漫画動画】
ランキングする前から,再生回数,高評価数ともに1位だったので,ランキングする前からスコア100で1位になるは目に見えていましたね.
動画の内容もとても良いので,まだ見てない人がいたら,今すぐリンクから動画を視聴してください.
2位: 【漫画】もしも小人になったらどうなるのか?…あんなコトやこんなコトが…??【アニメ】【漫画動画】
再生回数は300万回を下回るものの,高評価数で2位につけたため,本ランキングでも再生回数の差をはねのけて2位につけました.サムネイルと本編の内容が一致しており,好評??
3位: 【アニメ】整形中毒になるとどうなるのか…生まれ変われるってホント!?【漫画動画】
再生回数では300万越えで2位につけていましたが,高評価数の影響で3位になりました.少し前まで再生回数1位だったような...サムネイルと本編の内容が一致しており,好評??
4位: 5億年ボタンを押したらどうなるのか?【アニメ】【漫画動画】
再生回数が4位で,再生回数と同じ順位となりました.14:14 という珍しい長編となっており,内容もよいので素晴らしい動画です.ほかのYouTuber もこの手の内容の動画は再生回数多いですよね.
5位: 混浴風呂で知り合いと出会うとどうなるのか?【アニメ】【漫画動画】
再生回数6位で,高評価数7位です.2日前の動画に高評価数抜かれていましたが,人気の動画です.サムネイルと本編の内容が一致しており,好評??
6位: 【アニメ】冗談で告白した相手から恐怖の手紙が…→意外な真実が【漫画動画】
再生回数は5位,しかし高評価数は11位で,高評価数の影響により順位が微減しました.
サムネイルと本編の内容が一致しており,好評??
7位: 【漫画】お風呂で寝ると失神する!?お風呂に入るうえで注意した方が良いこと【アニメ】【漫画動画】
再生回数8位,高評価数12で,同じく高評価数で順位微減です.
こちらも,サムネイルと本編の内容が一致しており,好評??
8位: 首都直下地震が起きたらどうなるのか【アニメ】【漫画動画】
ランキングに入っている動画の中では,一番最近(2020/9/19)の動画です.
再生回数12位,高評価数10ですが,ランキング上位に入ってきました.
この動画の内容はためになる上に,最後が感動的でよかったです.
そのあたりが上位の入賞への原動力だったのかな...
9位: もし性別が入れ替わったらどうなるのか?【アニメ】【漫画動画】
こちらは,2020/9/1 公開で次に最近の動画ですね.
再生回数9位,高評価14位でした.
サムネイルが好評??
10位: 服が透けて見えるメガネを手にした男の夢ある行動とは…【アニメ】【漫画動画】
最後です.再生回数が200万回近くで7位,高評価数は17位です.
こちらも,サムネイルと本編の内容が一致しており,好評??
基本は,再生回数が上位の動画ほどランキング上位に来ますが,その中で高評価数により,順位が再生回数と異なる,という結果になりました.
最近公開された動画で特に高評価数が高い死亡フラグの1DAYルーティン【アニメ】【漫画動画】と,【究極の選択】金と人の命はどちらが大事なのか…?【アニメ】【漫画動画】が,もう少しして再生回数が高評価数に追いつくほど増えてきたら,ランキングがどう変わってくるのか興味があります.(各々スコアは現時点で21.49と8.94でした.前者はもう少しかも...)
簡単なまとめ
- 勝手にスコアを定義してランキング付け面白かった
- 正規化も正しくしてあげないと,見栄えが微妙になる
- 高評価でランキング付けると最近の動画が出てきて面白かった
- やっぱNo. 1は【無痛症】痛みを感じなくなった男の末路…【アニメ】【漫画動画】だった
- ランキング上位の動画はサムネイルと本編の内容が一致していることが,人気の秘訣っぽい
今後の予定
他にも気になることがあったら,記事を作成していきます.
今回紹介した動画
上に書いたので,省略します.
おわりに
公式でも視聴者に対して人気投票を1周年記念 の際に実施していましたが,その結果が本記事の結果とどれくらい異なってくるのか,楽しみです.一応今回のランキング上位に来た動画は投票の際にはすでに公開されていた動画なので,すべて見比べることができるはずです.
公式の投票は視聴者の主観的なランキング,今回実施したのは再生回数と高評価数という2つの数値によるランキング,どう異なってくるのか非常に楽しみです.
ここまで読んでいる人はいないと思いますが,もしいたらまずは,以下のリンクから全力回避フラグちゃん! チャンネルとフラグちゃんのTwitter をフォローしてください.この記事を読むより大切なことです.
大事なことなのでもう一度,チャンネル登録とTwitter のフォローをよろしくお願いいたします.
関連リンク
- 全力回避フラグちゃん! https://www.youtube.com/channel/UCo_nZN5yB0rmfoPBVjYRMmw/videos
- 株式会社Plott / Plott Inc. https://plott.tokyo/#top
- フラグちゃんのTwitter https://twitter.com/flag__chan
- Github https://github.com/uky007/flag_analysis
おまけ
再生回数と高評価をプロットしているプログラムに,スコアを計算する記述を追加しています.
import os
import sys
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime
import matplotlib.dates as mdates
import matplotlib.patches as mpatches
from matplotlib.path import Path
import matplotlib
from matplotlib.font_manager import FontProperties
from matplotlib import rcParams
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
#データセット対象のCSV ファイル
file = sys.argv[1]
output_file = sys.argv[2]
#Date, 再生回数
num_play = pd.read_csv(file, header=0, encoding='UTF8', usecols=[3, 5], parse_dates=[0])
num_play = num_play.dropna(how='all')
#Date, Like
num_like = pd.read_csv(file, header=0, encoding='UTF8', usecols=[3, 6], parse_dates=[0])
num_like = num_like.dropna(how='all')
#Date, DisLike
num_dislike = pd.read_csv(file, header=0, encoding='UTF8', usecols=[3, 7], parse_dates=[0])
num_dislike = num_dislike.dropna(how='all')
#Date, コメント数
num_comment = pd.read_csv(file, header=0, encoding='UTF8', usecols=[3, 8], parse_dates=[0])
num_comment = num_comment.dropna(how='all')
#Plot するグラフ
#Date
x = num_play[num_play.columns[0]]
#x = pd.date_range(x[0], x[218], freq='D')
#再生回数
y1 = num_play[num_play.columns[1]]
#Like
y2 = num_like[num_like.columns[1]]
#DisLike
y3 = num_dislike[num_dislike.columns[1]]
#コメント
y4 = num_comment[num_comment.columns[1]]
#########################################
#Score
vn = []
ln = []
score = []
for i in range(len(num_play)):
vn.append((y1[i] - min(y1)) / (max(y1) - min(y1)))
ln.append((y2[i] - min(y2)) / (max(y2) - min(y2)))
score.append(vn[i] * ln[i] * 100)
df = pd.DataFrame(score)
df.index = np.arange(1, len(df) + 1)
df.to_csv("flag_videos_score.csv", header=False, index=True)
##########################################
#フォント設定
#plt.rcParams['font.family'] = 'Times New Roman'
font_path = '/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf'
font_prop = FontProperties(fname=font_path)
matplotlib.rcParams['font.family'] = font_prop.get_name()
fig = plt.figure(figsize=(20.0, 12.0), dpi=300)
ax1 = fig.add_subplot()
# グラフプロット
## 再生回数を棒グラフでプロット
play = ax1.bar(x, y1, width=1.0, bottom=None, color="lightblue")
## Like, Dislike, Commnetを折れ線でプロット
ax2 = ax1.twinx()
like, = ax2.plot(x, y2, color='r')
dislike, = ax2.plot(x, y3, color='b')
comment, = ax2.plot(x, y4, color='k')
##### Story #################################################################################
s1, = ax2.plot(x[59], y2[59], marker='*', markersize=20, color='#ff7f00', linestyle='None')
s2, = ax2.plot(x[74], y2[74], marker='*', markersize=20, color='#ff7f00', linestyle='None')
s3, = ax2.plot(x[95], y2[95], marker='*', markersize=20, color='#ff7f00', linestyle='None')
s4, = ax2.plot(x[125], y2[125], marker='*', markersize=20, color='#ff7f00', linestyle='None')
s5, = ax2.plot(x[195], y2[195], marker='*', markersize=20, color='#ff7f00', linestyle='None')
s6, = ax2.plot(x[228], y2[228], marker='*', markersize=20, color='#ff7f00', linestyle='None')
##############################################################################################
# 軸の範囲
ax1.set_xlim('2019-11-01', x[len(x) - 1])
ax1.set_ylim([0, 3500000])
ax2.set_ylim([0, 30000])
print("Sum of likeCount:" + str(sum(y2)))
print("Max likeCount:" + str(max(y2)))
print("Average likeCount:" + str(num_like.mean(axis=0)))
print("Median likeCount:" + str(num_like.median(axis=0)))
print("Max comment count:" + str(max(y4)))
print("Average comment count:" + str(num_comment.mean(axis=0)))
print("Median comment count:" + str(num_comment.median(axis=0)))
# グラフタイトル
ax1.set_title("全力回避フラグちゃん! 再生回数と評価数", fontname="TakaoPGothic", fontsize=20)
# 軸メモリ
ax1.tick_params(axis='x', labelsize=20, labelrotation=45)
ax1.tick_params(axis='y', labelsize=20)
ax2.tick_params(axis='y', labelsize=20)
# ラベル名
ax1.set_xlabel("動画公開日", fontsize=20, fontname="TakaoPGothic")
ax1.set_ylabel("再生回数", fontname="TakaoPGothic", fontsize=20)
ax2.set_ylabel("評価/コメント数", fontname="TakaoPGothic", fontsize=20, rotation=270, labelpad=30)
# 凡例
play_title = "再生回数"
like_title = "高評価"
dislike_title = "低評価"
comment_title = "コメント"
s_title = "ストーリー編"
plt.legend([play, like, dislike, comment, s1], [play_title, like_title, dislike_title, comment_title, s_title], bbox_to_anchor=(1.0, 1.0), prop={"family":"TakaoPGothic", 'size':20}, markerscale=3)
#画像保存
plt.savefig(output_file, bbox_inches="tight", pad_inches=0.0)