番組滞在率の調査

番組滞在率の調査

概要

  • 調査対象期間 : 2018/03/01 – 2018/03/31
  • 弊社チューナの利用履歴のログよりチューナの視聴状態を抽出
  • TV番組の放送時間に対して1ユーザが平均でどの程度滞在するのかを調査しました
  • 平均PTが15以上の番組のみ対象としています(少なすぎるケースを除外)
  • 放送時間が15分以上の番組を対象としています

用語

  • 番組滞在率
    • (番組中の1ユーザ平均視聴時間 / 番組放送時間) * 100で計算
    • ユーザが平均で番組放送時間の何%滞在したかを表現しています
    • 例えば1時間の番組で25%の場合、ユーザが平均で放送時間の25%を視聴(1時間中の15分滞在)となります
    • 表中ではrateと表記しています
  • PT

制限事項

  • 東京の放送局限定
  • 1分以上の視聴を行ったユーザのみ対象(ザッピングを除去)
  • 番組滞在率は番組評価値ではありません
    • 後述するように単純に長時間番組の方が低い傾向にあります
    • 滞在率は低くても番組を視聴したユニークユーザ数は多いケースもあります
In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as tc
%matplotlib inline

plt.rcParams['font.family'] = 'IPAPGothic'

データ読み出し

  • 視聴データを保存しているAzureのデータベースにクエリを行い、必要なデータをjsonで保存
  • pandasでjson読み出し
  • 平均PTが20以上、放送時間が15分以上の番組に絞る
In [2]:
df = pd.read_json('program_summary.json', encoding='shift-jis', lines=True)
df = df.loc[(df['total_duration_sec'] / df['program_duration_sec'] >= 20.0) & (df['program_duration_sec'] >= 15*60)].reset_index(drop=True)

番組滞在率を計算

In [3]:
def get_rate(row):
    try:
        return round(100.0 * row['total_duration_sec'] / row['unique_user'] / row['program_duration_sec'], 2)
    except:
        pass
    return 0

df['rate'] = df.apply(get_rate, axis=1)

# 不要カラムの削除
df = df.drop(['base_sv_id', 'event_id', 'total_duration_sec', 'unique_user'], axis=1)

番組滞在率が高い5番組

  • NHKの朝の連続ドラマが高く独占
  • 15分と短く、ドラマなので最初から最後まで見るユーザが多いと考えます
In [4]:
df.sort_values('rate', ascending=False).reset_index(drop=True).head(5)
Out[4]:
genre_name program_duration_sec program_name start_time rate
0 ドラマ 900 連続テレビ小説 わろてんか(149)「みんなでわろてんか」 2018-03-29 12:45:00 88.88
1 ドラマ 900 連続テレビ小説 わろてんか(146)「みんなでわろてんか」 2018-03-26 12:45:00 88.16
2 ドラマ 900 連続テレビ小説 わろてんか(150)「みんなでわろてんか」 2018-03-30 12:45:00 88.13
3 ドラマ 900 連続テレビ小説 わろてんか(144)「さらば北村笑店」 2018-03-23 08:00:00 87.68
4 ドラマ 900 連続テレビ小説 わろてんか(135)「見果てぬ夢」 2018-03-13 08:00:00 86.96

「わろてんか」除外して確認してみる

  • 「わろてんか」以外の上位番組を確認するためざっくり判定でわろてんかを除外
  • 深夜帯の30分バラエティ番組が目立つ
  • 短時間のため視聴の離脱が少なく、深夜帯なので視聴目的がはっきりしている(その番組を見るためチャンネルを合わせている)と考えます
In [5]:
df.loc[~df['program_name'].str.contains('わろてんか')].sort_values('rate', ascending=False).reset_index(drop=True).head(5)
Out[5]:
genre_name program_duration_sec program_name start_time rate
0 バラエティ 1800 乃木坂工事中「必見!7年目の目標発表会!」 2018-03-19 00:00:00 85.32
1 バラエティ 1800 『ぷっ』すま 2018-03-24 01:00:00 84.20
2 バラエティ 1800 イッテンモノ 2018-03-08 00:15:00 83.93
3 バラエティ 1800 欅って、書けない?【6thシングルキャンペーン】 2018-03-05 00:35:00 80.35
4 バラエティ 1800 乃木坂工事中「必見!生駒最後の選抜発表!」 2018-03-12 00:00:00 78.96

番組滞在率が低い5番組

  • 深夜帯以外の長時間番組が目立つ
  • 単純に放送時間が長く、途中で視聴開始、終了のケースが多いと考えられる
  • モバイルで視聴しているユーザはバッテリーを気にして数時間の連続視聴を行わない可能性も高そうです
In [6]:
df.sort_values('rate', ascending=True).reset_index(drop=True).head(5)
Out[6]:
genre_name program_duration_sec program_name start_time rate
0 バラエティ 19380 オールスター感謝祭'18春 2018-03-31 18:25:00 16.67
1 スポーツ 11640 Fun!BASEBALL‼プロ野球開幕戦「巨人×阪神」&開幕全試合情報⚾‼ 2018-03-30 17:50:00 20.27
2 ニュース/報道 12600 ひるおび! 速報!参院で集中審議・森友文書改ざん追及本格化▽桜スピード開花 2018-03-19 10:25:00 21.61
3 ニュース/報道 11400 news every.藤井貴彦、小山慶一郎がきょう一日を分かりやすく 2018-03-05 15:50:00 21.63
4 ニュース/報道 11400 news every.藤井貴彦、小山慶一郎がきょう一日を分かりやすく 2018-03-26 15:50:00 21.72

ここまでのユーザ視聴時間レートのまとめ(推測込み)

  • 放送時間が短いと高く、長いと低い傾向がある
  • 放送時間帯が深夜の場合は高い傾向がありそう
  • レートの高低で単純に番組の評価はできなさそう

放送時間、放送開始時刻別にクラス分けしてユーザ視聴時間レートの統計量を出力

  • 放送時間の長さがレート自体に影響を与えているようなので放送時間をクラス分けしてみる

※単位は分
※15分未満は前処理で除外

  • 放送時間長
  • 0 : [15,45)
  • 1 : [45,75)
  • 2 : [75,105)
  • 3 : [105,135)
  • 4 : 135以上
  • 放送開始時刻
  • 0 : [23:00,05:00)
  • 1 : [05:00,11:00)
  • 2 : [11:00,17:00)
  • 3 : [17:00,23:00)
In [7]:
def get_type_val(val):
    if val >= 15*60 and val < 45*60:
        return 0
    elif val >= 45*60 and val < 75*60:
        return 1
    elif val >= 75*60 and val < 105*60:
        return 2
    elif val >= 105*60 and val < 135*60:
        return 3   
    if val >= 135*60:
        return 4
    return -1

def get_start_type(val):
    hour = val.hour
    if hour >= 23 or hour < 5:
        return 0
    elif hour >= 5 and hour < 11:
        return 1 
    elif hour >= 11 and hour < 17:
        return 2
    elif hour >= 17 and hour < 23:
        return 3
    
df['duration_type'] = df['program_duration_sec'].apply(get_type_val)
df['start_type'] = df['start_time'].apply(get_start_type)

放送時間別の番組滞在率

  • 横軸 : 番組放送時間
  • 縦軸 : 番組滞在率(ジャンル別)
  • 特定の放送時間長の番組が無い場合もあるのでその場合は欠けたままにしています
  • 放送時間が長いほど滞在率も低下する傾向にある
  • どのジャンルも似たような傾向にあるが、ドラマは他よりも高め
  • 音楽と映画にも特徴があるように見えますが番組数自体が数番組のため傾向と判断するのは危険
In [8]:
x_ax = range(5)
genre_list = df['genre_name'].unique()

y_ax_list = []
for x in genre_list:
    gr_df = df.loc[df['genre_name'] == x]
    y_ax = []
    for x_val in x_ax:
        dr_df = gr_df.loc[gr_df['duration_type'] == x_val]
        y_ax.append(np.nan if len(dr_df) == 0 else dr_df['rate'].mean())
    y_ax_list.append(y_ax)


plt.figure(figsize=(12,7))
plt.gca().xaxis.set_major_locator(tc.MaxNLocator(integer=True))


for y, g in zip(y_ax_list, genre_list):
    plt.plot(x_ax, y, marker='.', label=g)

plt.xlabel('放送時間長')
plt.xticks(range(5), ('15-44分', '45-74分', '75-104分', '105-134分', '135分以上'))
plt.ylabel('番組滞在率(%)')
plt.legend(loc="best")
plt.show()

放送開始時間別の番組滞在率

  • 番組ジャンルによっては放送していない時間帯もあるため欠けが多い
  • ドラマとバラエティに着目
    • ドラマは朝の連続ドラマが影響して朝が高い
    • バラエティは深夜帯が高い
In [9]:
x_ax = range(4)
genre_list = df['genre_name'].unique()

y_ax_list = []
for x in genre_list:
    gr_df = df.loc[df['genre_name'] == x]
    y_ax = []
    for x_val in x_ax:
        dr_df = gr_df.loc[gr_df['start_type'] == x_val]
        y_ax.append(np.nan if len(dr_df) == 0 else dr_df['rate'].mean())
    y_ax_list.append(y_ax)


plt.figure(figsize=(12,7))
plt.gca().xaxis.set_major_locator(tc.MaxNLocator(integer=True))


for y, g in zip(y_ax_list, genre_list):
    plt.plot(x_ax, y, marker='.', label=g)

plt.xlabel('放送時間長')
plt.xticks(range(4), ('深夜', '朝', '昼', '夜'))
plt.ylabel('番組滞在率(%)')
plt.legend(loc="best")
plt.show()

番組数が10以上に絞って標準偏差が大きい順に並べ替え

  • 以下が標準偏差が大きい
  • 放送時間が45-74分で17:00-23:00の開始時刻のドラマ
  • 放送時間が15-44分で23:00-05:00の開始時刻のバラエティ
In [10]:
dc_df = df.groupby(['duration_type', 'start_type', 'genre_name'])['rate'].describe()
dc_df.loc[dc_df['count'] >= 10].sort_values('std', ascending=False).head(10)
Out[10]:
count mean std min 25% 50% 75% max
duration_type start_type genre_name
1 3 ドラマ 32.0 61.065000 8.653985 45.46 55.1975 59.120 68.6975 77.62
0 0 バラエティ 54.0 68.384815 8.645812 48.85 62.1225 66.945 74.9675 85.32
1 ニュース/報道 34.0 60.176765 8.031511 47.45 52.7950 59.175 66.5400 77.30
1 0 バラエティ 29.0 57.256552 7.193904 37.26 53.2400 58.370 61.2700 72.43
3 バラエティ 92.0 50.239565 7.134820 33.95 45.4150 49.915 55.0775 67.70
0 2 バラエティ 11.0 64.956364 6.880261 53.13 61.4150 65.230 68.7300 77.52
1 情報/ワイドショー 20.0 63.677000 6.815824 47.68 61.5275 64.085 67.5700 75.54
1 2 ドラマ 29.0 62.622759 5.566656 52.83 58.5500 63.280 65.7100 75.04
3 3 バラエティ 40.0 35.119250 5.449292 24.81 30.3400 34.380 39.4125 48.59
0 3 ニュース/報道 47.0 65.709787 5.409146 52.60 62.6900 65.880 69.3400 74.51

放送時間が45-74分で17:00-23:00の開始時刻のドラマの上位、下位10

  • 西郷どん、アンナチュラル、99.9が高く、複数上位に入っている
  • 下位の方も同じドラマが複数回入っていることからドラマ別で傾向は分かれる模様
In [11]:
rank_df = df.loc[(df['duration_type'] == 1) & (df['start_type'] == 3) & (df['genre_name'] == 'ドラマ')].drop(['duration_type','start_type'], axis=1)
rank_df.sort_values('rate', ascending=False).reset_index(drop=True).head(10)
Out[11]:
genre_name program_duration_sec program_name start_time rate
0 ドラマ 2700 西郷どん(10)「篤姫はどこへ」 2018-03-11 20:00:00 77.62
1 ドラマ 2700 西郷どん(9)「江戸のヒー様」 2018-03-04 20:00:00 74.65
2 ドラマ 2700 西郷どん(12)「運の強き姫君」 2018-03-25 20:00:00 73.35
3 ドラマ 3240 金曜ドラマ「アンナチュラル」 第9話<敵の姿> 2018-03-09 22:00:00 73.04
4 ドラマ 2700 西郷どん(11)「斉彬暗殺」 2018-03-18 20:00:00 72.30
5 ドラマ 3840 金曜ドラマ「アンナチュラル」 最終話<旅の終わり> 2018-03-16 22:00:00 71.89
6 ドラマ 3240 99.9-刑事専門弁護士-SEASONⅡ ♯7「容疑者・佐田篤弘」 2018-03-04 21:00:00 71.12
7 ドラマ 3240 金曜ドラマ「アンナチュラル」 第8話<遥かなる我が家> 2018-03-02 22:00:00 70.01
8 ドラマ 3240 相棒 season 16 #19 2018-03-07 21:00:00 68.26
9 ドラマ 4440 99.9-刑事専門弁護士-SEASONⅡ ♯8 2018-03-11 21:00:00 65.71
In [12]:
rank_df.sort_values('rate', ascending=True).reset_index(drop=True).head(10)
Out[12]:
genre_name program_duration_sec program_name start_time rate
0 ドラマ 3600 anone#09 2018-03-14 22:00:00 45.46
1 ドラマ 3240 科捜研の女 #16 2018-03-08 20:00:00 48.35
2 ドラマ 3240 <木曜劇場>隣の家族は青く見える #09 2018-03-15 22:00:00 49.08
3 ドラマ 3240 バイプレイヤーズ〜もしも名脇役がテレ東朝ドラで無人島生活したら〜 2018-03-07 21:54:00 50.48
4 ドラマ 3240 火曜ドラマ「きみが心に棲みついた」第8話 最後のデート…悪魔の告白と涙のキス! 2018-03-06 22:00:00 51.45
5 ドラマ 3240 海月姫【奇跡は俺たちが作る!月海奪還大作戦】 #09 2018-03-12 21:00:00 53.57
6 ドラマ 3300 トドメの接吻#09 2018-03-04 22:30:00 53.90
7 ドラマ 3240 <木曜劇場>隣の家族は青く見える #10 2018-03-22 22:00:00 54.95
8 ドラマ 3240 火曜ドラマ「きみが心に棲みついた」第9話 復讐のパワハラ裁判、彼と決別する誕生日 2018-03-13 22:00:00 55.28
9 ドラマ 3240 科捜研の女 放送200回スペシャル #17 2018-03-15 20:00:00 56.01

まとめ

  • 番組滞在率が高い番組の特徴
    • 短時間(途中視聴開始、終了のケースが少ない)
    • ドラマ、映画など番組内容把握のため最初から最後まで見る必要があるジャンル
    • 深夜バラエティ
  • 番組滞在率が低い番組の特徴
    • 長時間(途中視聴開始、終了のケースが多い)
    • 朝のニュース、情報系番組
  • 放送時間、放送開始時刻、ジャンルが一致しても番組に依存して番組滞在率が異なるようです
  • 毎週放送する番組は同じ番組滞在率になることが多いようです
  • そのため平均PTが変わらなくても滞在率が大きく変化した回は何か特別なことがあった可能性がありそうです