下巻 第6章 練習問題#
ここでは、 本書の学習内容の定着 を目的とした練習問題を掲載します。 解答・解説は「解答例」ページを参照してください。 なお、問題の性質上、本書で取り上げた処理と重複することがあります。 ご了承ください。
前提#
以下のように、ライブラリのインポートと変数の定義が完了していることを前提とします。
Show code cell content
# difflibモジュールのインポート
# 文字列間の類似度や差異を計算するためのユーティリティを提供
import difflib
# itertoolsモジュールのインポート
# 様々なパターンのループを効率的に実行可能
import itertools
# pathlibモジュールのインポート
# ファイルシステムのパスを扱う
from pathlib import Path
# numpy:数値計算ライブラリのインポート
# npという名前で参照可能
import numpy as np
# pandas:データ解析ライブラリのインポート
# pdという名前で参照可能
import pandas as pd
# plotly.expressのインポート
# インタラクティブなグラフ作成のライブラリ
# pxという名前で参照可能
import plotly.express as px
# plotly.graph_objectsからFigureクラスのインポート
# 型ヒントの利用を主目的とする
from plotly.graph_objects import Figure
Show code cell content
# マンガデータの中間出力ファイルが格納されているディレクトリ
DIR_CM_INTERIM = Path("../../../data/cm/interim")
# アニメデータの中間出力ファイルが格納されているディレクトリ
DIR_AN_INTERIM = Path("../../../data/an/interim")
# アニメデータの入力ファイルが格納されているディレクトリ
DIR_AN_INPUT = Path("../../../data/an/input")
# 外部データソースから作成した対応表などを格納しているディレクトリ
DIR_MIX_EXTERNAL = Path("../../../data/mix/external")
# メディア展開データの入力ファイルが格納されているディレクトリ
DIR_MIX_INPUT = Path("../../../data/mix/input")
Show code cell content
# アニメ作品とマンガ作品の全対応関係が記されたファイル
FN_AC_CC = "ac_cc.csv"
# マンガ作品の結合用メタデータファイル
FN_CC_MERGE = "cc_merge.csv"
# アニメ作品の結合用メタデータファイル
FN_AC_MERGE = "ac_merge.csv"
# アニメ各話データのファイル
FN_AE = "an_ae.csv"
# アニメ各話と原作マンガの作者の対応関係に関するファイル
FN_AE_CRT = "mix_ae_crt.csv"
# マンガ各話とアニメ作品の対応関係に関するファイル
FN_CE_AC = "mix_ce_ac.csv"
Show code cell content
# plotlyの描画設定の定義
# plotlyのグラフ描画用レンダラーの定義
# Jupyter Notebook環境のグラフ表示に適切なものを選択
RENDERER = "plotly_mimetype+notebook"
# 質的変数の描画用のカラースケールの定義
# Okabe and Ito (2008)基準のカラーパレット
# 色の識別性が高く、多様な色覚の人々にも見やすい色組み合わせ
# 参考URL: https://jfly.uni-koeln.de/color/#pallet
OKABE_ITO = [
"#000000", # 黒 (Black)
"#E69F00", # 橙 (Orange)
"#56B4E9", # 薄青 (Sky Blue)
"#009E73", # 青緑 (Bluish Green)
"#F0E442", # 黄色 (Yellow)
"#0072B2", # 青 (Blue)
"#D55E00", # 赤紫 (Vermilion)
"#CC79A7", # 紫 (Reddish Purple)
]
また、本書中で取り上げた以下の関数も、同様に利用可能とします。
Show code cell source
def show_fig(fig: Figure) -> None:
"""
所定のレンダラーを用いてplotlyの図を表示
Jupyter Bookなどの環境での正確な表示を目的とする
Parameters
----------
fig : Figure
表示対象のplotly図
Returns
-------
None
"""
# 図の周囲の余白を設定
# t: 上余白
# l: 左余白
# r: 右余白
# b: 下余白
fig.update_layout(margin=dict(t=25, l=25, r=25, b=25))
# 所定のレンダラーで図を表示
fig.show(renderer=RENDERER)
Show code cell content
def resample_df_by_col_and_years(df: pd.DataFrame, col: str) -> pd.DataFrame:
"""
指定されたカラムと年数に基づき、データフレームを再サンプル
colとyearsの全ての組み合わせが存在するように0埋めを行う
この処理は、作図時にX軸方向の順序が変わることを防ぐために必要
Parameters
----------
df : pd.DataFrame
入力データフレーム
col : str
サンプリング対象のカラム名
Returns
-------
pd.DataFrame
再サンプルされたデータフレーム
"""
# 入力データフレームを新しい変数にコピー
df_new = df.copy()
# データフレームからユニークな年数一覧を取得
unique_years = df["years"].unique()
# データフレームからユニークなcolの値一覧を取得
unique_vals = df[col].unique()
# 一意なカラムの値と年数の全ての組み合わせに対して処理
for val, years in itertools.product(unique_vals, unique_years):
# 対象のカラムの値と年数が一致するデータを抽出
df_tmp = df_new[(df_new[col] == val) & (df_new["years"] == years)]
# 該当するデータが存在しない場合
if df_tmp.shape[0] == 0:
# 0埋めのデータを作成
default_data = {c: 0 for c in df_tmp.columns}
# col列についてはvalで埋める
default_data[col] = val
# years列についてはyearで埋める
default_data["years"] = years
# 新たなレコードとして追加
df_add = pd.DataFrame(default_data, index=[0])
# 0埋めのデータをデータフレームに追加
df_new = pd.concat([df_new, df_add], ignore_index=True)
return df_new
また、以下のようにデータを読み込み済みと仮定します。
Show code cell content
# 全てのメディア展開を網羅する対応表の読み込み
df_ac_cc = pd.read_csv(DIR_MIX_EXTERNAL / FN_AC_CC)
# マンガ作品メタデータの読み込み(日付列を日時型として解釈)
df_cc_merge = pd.read_csv(DIR_CM_INTERIM / FN_CC_MERGE, parse_dates=["first_date"])
# アニメ作品メタデータの読み込み(日付列を日時型として解釈)
df_ac_merge = pd.read_csv(DIR_AN_INTERIM / FN_AC_MERGE, parse_dates=["first_date"])
# アニメ各話データの読み込み
df_ae = pd.read_csv(DIR_AN_INPUT / FN_AE)
# アニメ各話と原作マンガの作者の対応関係データの読み込み
df_ae_crt = pd.read_csv(DIR_MIX_INPUT / FN_AE_CRT)
# マンガ各話とアニメ作品の対応関係データの読み込み
df_ce_ac = pd.read_csv(DIR_MIX_INPUT / FN_CE_AC)
基礎 問題1:マンガ作者別のアニメ放送話数#
関連セクション: 棒グラフ
本文では、マンガ作者別のアニメ合計放送話数を 縦棒グラフ で可視化しました。 ここでは、同様のデータを 横棒グラフ で可視化してみましょう。
df_ae_crtを用いて、マンガ作者名(crtname)ごとにアニメ各話ID(aeid)のユニーク数を集計してください集計結果を降順にソートし、上位 10件 に絞り込んでください(本文では20件)
px.bar()を用いて 横棒グラフ を作成してください
ヒント
横棒グラフにするには
orientation="h"を指定します横棒グラフでは x と y の指定が縦棒グラフと逆になります
例:
px.bar(..., orientation="h")でアニメ各話数が20未満の作品
基礎 問題2:掲載特性の散布図行列#
関連セクション: 散布図行列
本文では、マンガ作品の掲載特性を「平均掲載位置」「平均ページ数」「カラー獲得率」「連載開始日」の 4変数 で散布図行列にしました。 ここでは、「連載開始日」を除いた 3変数 で散布図行列を作成してみましょう。
df_ce_acを用いて、本文と同様にマンガ作品ごとの最初の8話分の掲載特性を集計してくださいpx.scatter_matrix()を用いて、「平均掲載位置」「平均ページ数」「カラー獲得率」の 3変数 で散布図行列を作成してくださいアニメ化有無(
is_animated)で色分けしてください
ヒント
dimensions引数に表示したい変数名のリストを指定します例:
px.scatter_matrix(..., dimensions=["変数A", "変数B"])で2変数のみ表示
標準 問題3:週刊少年サンデーのアニメ化推移#
関連セクション: 積上げ密度プロット
本文では、4つの雑誌すべてを対象に、連載開始年ごとのアニメ化作品数の推移を積上げ密度プロットで可視化しました。 ここでは、週刊少年サンデー に絞り込んで同様の可視化を行ってみましょう。
df_ce_acから 週刊少年サンデー のデータのみをフィルタリングしてください連載開始年(
first_date_ccの年)とアニメ化有無でグループ化し、マンガ作品数を集計してくださいpx.area()を用いて積上げ密度プロットを作成してください
ヒント
雑誌名でフィルタリングするには
df[df["mcname"] == "週刊少年サンデー"]のようにします例:
df[df["platform"] == "Switch"]でSwitchプラットフォームのみに絞り込み
標準 問題4:変数配置を変えたバブルチャート#
関連セクション: バブルチャート
本文では、マンガ作品の掲載特性をバブルチャートで可視化しました。その際、以下のように変数を配置しました:
x軸:平均掲載位置
y軸:平均ページ数
size:カラー獲得率
ここでは、変数の配置を変えて、カラー獲得率をx軸に、平均掲載位置をsizeに 設定したバブルチャートを作成してみましょう。
問題2と同様に、
df_ce_acから掲載特性のデータを準備してくださいpx.scatter()を用いて、以下の配置でバブルチャートを作成してください:x軸:カラー獲得率
y軸:平均ページ数
size:平均掲載位置
ヒント
バブルチャートは
px.scatter()にsize引数を追加することで作成できます例:
px.scatter(..., size="売上")で売上を円のサイズに反映
応用 問題5:アニメ化までのリードタイム#
関連セクション: ヒストグラム
マンガ作品が連載を開始してから、アニメが放送されるまでにどれくらいの期間(インターバル)があるかを可視化しましょう。
第6章で学んだ「分布を見るための手法」と「ファセット」を活用してください。
読み込んだ
df_ac_ccを主軸とし、マンガの連載開始日(first_date)とアニメの放送開始日(first_date)をそれぞれ結合して一つのデータフレームを作成してください「アニメ放送開始日 - マンガ連載開始日」を計算し、経過年数を算出してください
マンガ雑誌(
mcname)ごとに、この経過日数の分布をヒストグラムで可視化してください可視化に際しては、雑誌ごとの傾向の違いが比較しやすいよう、ファセット機能を利用してください
ヒント
データの結合には
pd.merge()を使用します日付の差分は
.dt.daysで日数に変換できますヒストグラムには
px.histogram()を使用しますファセットは
facet_col引数で指定できます
応用 問題6:アニメ各話数における原作区分の推移#
関連セクション: 積上げ密度プロット
1990年以降の全アニメ作品の各話数に対して、「四大少年誌を原作とするアニメ」が占める割合がどのように推移してきたかを可視化しましょう。
アニメ産業の規模の変化と、その中での四大少年誌の影響力を同時に確認するために、以下の2つの図を作成してください。
絶対数の推移: 年度ごとのアニメ総話数を、原作の区分(「四大少年誌」または「その他」)で積み上げた積上げ密度プロット(エリアチャート)
割合の推移: 年度ごとの総話数を1(100%)とした時の、各区分の構成比を示した積上げ密度プロット(エリアチャート)
ヒント
アニメ各話データ(
df_ae)とメディア展開対応表(df_ac_cc)を統合して利用しますdf_ac_ccに含まれるacidはすべて四大少年誌原作の作品です可視化には
px.area()を使用します引数として
groupnorm='fraction'を用いると、別途DataFrameを集計することなく構成比の可視化が可能になります
応用 問題7:マンガ作品名とアニメ作品名の類似度#
関連セクション: 箱ひげ図
マンガ作品がアニメ化される際、作品名がそのまま使われることもあれば、サブタイトルが追加されたり、全く異なる名称に変更されることもあります。 この「作品名の類似度」は、メディア展開の戦略を反映している可能性があります。
本書で学んだ difflib.SequenceMatcher を用いて、マンガ作品名(ccname)とアニメ作品名(acname)の類似度を計算し、その分布を雑誌ごとに比較してみましょう。
df_ac_ccを主軸として、マンガ作品名(ccname)とアニメ作品名(acname)を結合してください。雑誌名(mcname)も含めてくださいdifflib.SequenceMatcherのratio()メソッドを用いて、各行のccnameとacnameの類似度(0〜1)を計算してください雑誌ごとの類似度の分布を 箱ひげ図 で可視化してください
ヒント
difflib.SequenceMatcher(None, str1, str2).ratio()で2つの文字列の類似度が得られます箱ひげ図には
px.box()を使用しますapply()メソッドで各行に関数を適用できます
応用 問題8:マンガ話数とアニメ話数の関係#
関連セクション: 散布図
マンガ作品の連載話数とアニメ作品の放送話数には、どのような関係があるでしょうか? 直感的には「マンガの話数が多いほど、アニメの話数も多くなる」と予想されますが、実際のデータはこの仮説を支持するでしょうか。
df_ac_cc で紐づけられたマンガ作品とアニメ作品について、それぞれの話数の関係を散布図で可視化してみましょう。
df_ac_ccを主軸として、マンガ作品の話数(n_ce)とアニメ作品の話数(n_ae)を結合してください。作品名と放送開始日も含めてくださいアニメの放送開始日から「放送年」を抽出してください
マンガ話数をX軸、アニメ話数をY軸とした散布図を作成し、放送年で色分けしてください
ホバー時にマンガ作品名とアニメ作品名が確認できるようにしてください
ヒント
散布図には
px.scatter()を使用しますホバー情報は
hover_data引数で指定できます重複が多い場合は
update_traces()でマーカーの透明度やサイズを調整すると見やすくなります