下巻 第6章 練習問題#

ここでは、 本書の学習内容の定着 を目的とした練習問題を掲載します。 解答・解説は「解答例」ページを参照してください。 なお、問題の性質上、本書で取り上げた処理と重複することがあります。 ご了承ください。

前提#

以下のように、ライブラリのインポートと変数の定義が完了していることを前提とします。

Hide 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
Hide 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")
Hide 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"
Hide 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)
]

また、本書中で取り上げた以下の関数も、同様に利用可能とします。

Hide 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)
Hide 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

また、以下のようにデータを読み込み済みと仮定します。

Hide 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() を用いて 横棒グラフ を作成してください

基礎 問題2:掲載特性の散布図行列#

関連セクション: 散布図行列

本文では、マンガ作品の掲載特性を「平均掲載位置」「平均ページ数」「カラー獲得率」「連載開始日」の 4変数 で散布図行列にしました。 ここでは、「連載開始日」を除いた 3変数 で散布図行列を作成してみましょう。

  • df_ce_ac を用いて、本文と同様にマンガ作品ごとの最初の8話分の掲載特性を集計してください

  • px.scatter_matrix() を用いて、「平均掲載位置」「平均ページ数」「カラー獲得率」の 3変数 で散布図行列を作成してください

  • アニメ化有無(is_animated)で色分けしてください

標準 問題3:週刊少年サンデーのアニメ化推移#

関連セクション: 積上げ密度プロット

本文では、4つの雑誌すべてを対象に、連載開始年ごとのアニメ化作品数の推移を積上げ密度プロットで可視化しました。 ここでは、週刊少年サンデー に絞り込んで同様の可視化を行ってみましょう。

  • df_ce_ac から 週刊少年サンデー のデータのみをフィルタリングしてください

  • 連載開始年(first_date_cc の年)とアニメ化有無でグループ化し、マンガ作品数を集計してください

  • px.area() を用いて積上げ密度プロットを作成してください

標準 問題4:変数配置を変えたバブルチャート#

関連セクション: バブルチャート

本文では、マンガ作品の掲載特性をバブルチャートで可視化しました。その際、以下のように変数を配置しました:

  • x軸:平均掲載位置

  • y軸:平均ページ数

  • size:カラー獲得率

ここでは、変数の配置を変えて、カラー獲得率をx軸に、平均掲載位置をsizeに 設定したバブルチャートを作成してみましょう。

  • 問題2と同様に、df_ce_ac から掲載特性のデータを準備してください

  • px.scatter() を用いて、以下の配置でバブルチャートを作成してください:

    • x軸:カラー獲得率

    • y軸:平均ページ数

    • size:平均掲載位置

応用 問題5:アニメ化までのリードタイム#

関連セクション: ヒストグラム

マンガ作品が連載を開始してから、アニメが放送されるまでにどれくらいの期間(インターバル)があるかを可視化しましょう。

第6章で学んだ「分布を見るための手法」と「ファセット」を活用してください。

  • 読み込んだ df_ac_cc を主軸とし、マンガの連載開始日(first_date)とアニメの放送開始日(first_date)をそれぞれ結合して一つのデータフレームを作成してください

  • 「アニメ放送開始日 - マンガ連載開始日」を計算し、経過年数を算出してください

  • マンガ雑誌(mcname)ごとに、この経過日数の分布をヒストグラムで可視化してください

  • 可視化に際しては、雑誌ごとの傾向の違いが比較しやすいよう、ファセット機能を利用してください

応用 問題6:アニメ各話数における原作区分の推移#

関連セクション: 積上げ密度プロット

1990年以降の全アニメ作品の各話数に対して、「四大少年誌を原作とするアニメ」が占める割合がどのように推移してきたかを可視化しましょう。

アニメ産業の規模の変化と、その中での四大少年誌の影響力を同時に確認するために、以下の2つの図を作成してください。

  • 絶対数の推移: 年度ごとのアニメ総話数を、原作の区分(「四大少年誌」または「その他」)で積み上げた積上げ密度プロット(エリアチャート)

  • 割合の推移: 年度ごとの総話数を1(100%)とした時の、各区分の構成比を示した積上げ密度プロット(エリアチャート)

応用 問題7:マンガ作品名とアニメ作品名の類似度#

関連セクション: 箱ひげ図

マンガ作品がアニメ化される際、作品名がそのまま使われることもあれば、サブタイトルが追加されたり、全く異なる名称に変更されることもあります。 この「作品名の類似度」は、メディア展開の戦略を反映している可能性があります。

本書で学んだ difflib.SequenceMatcher を用いて、マンガ作品名(ccname)とアニメ作品名(acname)の類似度を計算し、その分布を雑誌ごとに比較してみましょう。

  • df_ac_cc を主軸として、マンガ作品名(ccname)とアニメ作品名(acname)を結合してください。雑誌名(mcname)も含めてください

  • difflib.SequenceMatcherratio() メソッドを用いて、各行の ccnameacname の類似度(0〜1)を計算してください

  • 雑誌ごとの類似度の分布を 箱ひげ図 で可視化してください

応用 問題8:マンガ話数とアニメ話数の関係#

関連セクション: 散布図

マンガ作品の連載話数とアニメ作品の放送話数には、どのような関係があるでしょうか? 直感的には「マンガの話数が多いほど、アニメの話数も多くなる」と予想されますが、実際のデータはこの仮説を支持するでしょうか。

df_ac_cc で紐づけられたマンガ作品とアニメ作品について、それぞれの話数の関係を散布図で可視化してみましょう。

  • df_ac_cc を主軸として、マンガ作品の話数(n_ce)とアニメ作品の話数(n_ae)を結合してください。作品名と放送開始日も含めてください

  • アニメの放送開始日から「放送年」を抽出してください

  • マンガ話数をX軸、アニメ話数をY軸とした散布図を作成し、放送年で色分けしてください

  • ホバー時にマンガ作品名とアニメ作品名が確認できるようにしてください