下巻 第2章 練習問題#

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

前提#

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

Hide code cell content
# pathlibモジュールのインポート
# ファイルシステムのパスを扱う
from pathlib import Path

# typingモジュールからの型ヒント関連のインポート
# 関数やクラスの引数・返り値の型を注釈するためのツール
from typing import Any, Dict, List, Optional, Union

# numpy:数値計算ライブラリのインポート
# npという名前で参照可能
import numpy as np

# pandas:データ解析ライブラリのインポート
# pdという名前で参照可能
import pandas as pd

# plotly.expressのインポート
# インタラクティブなグラフ作成のライブラリ
# pxという名前で参照可能
import plotly.express as px

# plotly.figure_factoryのインポート
# 高度なプロットとデータ可視化のためのユーティリティ
# ffという名前で参照可能
import plotly.figure_factory as ff

# plotly.graph_objectsからFigureクラスのインポート
# 型ヒントの利用を主目的とする
from plotly.graph_objects import Figure

# plotly.subplotsからmake_subplotsのインポート
# 複数のサブプロットを含む複合的な図を作成する際に使用
from plotly.subplots import make_subplots
Hide code cell content
# マンガデータ保存ディレクトリのパス
DIR_CM = Path("../../../data/cm/input")
# アニメデータ保存ディレクトリのパス
DIR_AN = Path("../../../data/an/input")
# ゲームデータ保存ディレクトリのパス
DIR_GM = Path("../../../data/gm/input")
Hide code cell content
# 読み込み対象ファイル名の定義

# Comic Episode関連のファイル名
FN_CE = "cm_ce.csv"

# Anime Episode関連のファイル名
FN_AE = "an_ae.csv"

# PacKaGeとPlatForm関連のファイル名
FN_PKG_PF = "gm_pkg_pf.csv"
Hide code cell content
# plotlyの描画設定の定義

# plotlyのグラフ描画用レンダラーの定義
# Jupyter Notebook環境のグラフ表示に適切なものを選択
RENDERER = "plotly_mimetype+notebook"
Hide code cell content
# Okabe and Ito 2008
# 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 content
# 各プラットフォームのタイプをまとめた辞書
pfname2type = {
    "プレイステーション・ポータブル": "携帯型",
    "プレイステーション": "据置型",
    "プレイステーションVita": "携帯型",
    "プレイステーション3": "据置型",
    "プレイステーション2": "据置型",
}

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

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 create_distplot(
    df: pd.DataFrame,
    x: str,
    color: str = None,
    show_hist: bool = False,
    show_rug: bool = False,
    **kwargs: Any
) -> Figure:
    """
    データフレームから密度プロットとヒストグラムを作成する

    Parameters
    ----------
    df : pd.DataFrame
        プロットするデータを含むデータフレーム
    x : str
        密度プロットの描画対象とするカラム名
    color : str, optional
        データを分割する基準とするカラム名、指定しない場合はx列の全データを用いる
    show_hist : bool, optional
        ヒストグラムを表示するか否か、デフォルトはFalse
    show_rug : bool, optional
        ラグプロットを表示するか否か、デフォルトはFalse
    **kwargs
        ff.create_distplotに渡すその他のキーワード引数

    Returns
    -------
    Figure
        作成されたプロットのFigureオブジェクト
    """

    if color:
        # colorカラムの値でデータをグループ分け
        grouped = df.groupby(color)

        # 各グループのxカラムのデータをリストに格納、可視化用に逆順に並び替え
        hist_data = [group[x].values for _, group in grouped][::-1]

        # 各グループの名前(colorカラムの値)をラベルとしてリストに格納、可視化用に逆順に並び替え
        labels = [str(name) for name, _ in grouped][::-1]

        # 密度プロットとヒストグラムを作成
        fig = ff.create_distplot(
            hist_data, labels, show_hist=show_hist, show_rug=show_rug, **kwargs
        )
    else:
        # colorが指定されていない場合はx列の全データを用いる
        hist_data = [df[x].values]

        # 密度プロットを作成(ラベルはxを指定)
        fig = ff.create_distplot(
            hist_data,
            group_labels=[x],
            show_hist=show_hist,
            show_rug=show_rug,
            **kwargs
        )

    # x軸のタイトルをxに変更
    fig.update_xaxes(title=x)

    # y軸のタイトルを"確率密度"に変更
    fig.update_yaxes(title="確率密度")

    # 作成されたプロットを返す
    return fig

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

Hide code cell content
# マンガデータの読み込み
df_ce = pd.read_csv(DIR_CM / FN_CE)
# アニメデータの読み込み
df_ae = pd.read_csv(DIR_AN / FN_AE)
# ゲームデータの読み込み
df_pkg_pf = pd.read_csv(DIR_GM / FN_PKG_PF)

基礎 問題1:アニメ作品の合計話数の分布#

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

本書では、アニメ作品ごとの合計話数のヒストグラムを作成し、表示範囲を100話以下に制限して分布を観察しました。表示範囲を変えると、分布の見え方はどのように変わるでしょうか。

  • df_aeを用いて、アニメ作品ごとの合計話数を集計してください

  • 合計話数のヒストグラムを作成し、表示範囲を 50話 以下に制限してください

基礎 問題2:ゲーム価格の累積分布#

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

本書では、ゲームパッケージの価格の累積ヒストグラムを作成し、10,000円以下の範囲で累積分布を確認しました。表示範囲を広げると、価格分布の全体像がより明確になります。

  • df_pkg_pfを用いて、ゲームパッケージの価格の累積ヒストグラムを作成してください

  • 表示範囲を 15,000円 以下に制限してください

標準 問題3:週刊少年ジャンプのページ数分布#

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

本文では、4誌すべてのページ数分布をファセット表示で比較しました。特定の雑誌に絞り込むと、その雑誌固有の特徴がより詳細に観察できます。

  • df_ceから週刊少年ジャンプのデータのみに絞り込んでください

  • 一話あたりのページ数(50ページ以下)のヒストグラムを作成してください

  • ビン数を25に設定してください

標準 問題4:プレイステーション2の価格分布#

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

本文の箱ひげ図では、プレイステーションシリーズの価格分布を中央値や四分位範囲で要約しました。しかし、箱ひげ図では分布の詳細な形状は見えません。特定のプラットフォームに絞り、ヒストグラムで分布を詳しく観察してみましょう。

  • df_pkg_pfからプレイステーション2のデータのみに絞り込んでください

  • 価格のヒストグラムを作成してください

  • 表示範囲を10,000円以下に制限してください

発展 問題5:ページ数分布の話数別変化#

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

連載の長さによって、1話あたりのページ数にどのような違いがあるでしょうか。読み切り作品(1話完結)と短期連載では、ページ数の決まり方が異なるかもしれません。

  • ccid(作品ID)ごとに合計話数を算出し、df_ce に結合してください

  • 合計話数が「1話」から「10話」までの作品に限定し、ページ数(50ページ以下)のヒストグラムをファセット表示で比較してください

  • ファセットは合計話数を基準に分けてください

発展 問題6:プレイステーションシリーズの価格帯比較#

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

ゲームプラットフォームの世代交代と販売価格の関係を整理しましょう。プレイステーションシリーズ5機種を対象に、「据置型」と「携帯型」で価格分布がどう異なるかを比較します。

  • 辞書pfname2typeを用いて各機種を「据置型」と「携帯型」に分類してください

  • 横軸を分類、縦軸を販売価格とした箱ひげ図を作成してください

応用 問題7:平日・土日の話数分布の推移#

関連セクション: リッジラインプロット

本章では、深夜アニメの台頭によりクール化が進んだ可能性が示唆されました。この傾向を「平日(月〜金)」と「土日」の放送枠で分けて分析してみましょう。

  • 曜日情報を抽出し、「平日」と「土日」に分類してください

  • 平日と土日の両方で放送データが存在する作品は除外 してください(厳密な比較のため)

  • 1990年代、2000年代、2010年代の作品について、年代ごとの合計話数分布(100話以下)をリッジラインプロットで比較してください

応用 問題8:最終回の掲載位置分布#

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

マンガ作品の「最終回」は、雑誌のどのあたりに掲載される傾向があるでしょうか。巻頭カラーで華々しく飾られる作品もあれば、そうでない作品もありそうです。

  • 各作品の「最後の一話」を特定し、その掲載位置(page_start_position)を抽出してください

  • ただし、データセット末尾の作品は連載中の可能性があります(右側打ち切り)。各雑誌の最新巻号に掲載されていない作品のみ を対象としてください[1]

  • 雑誌ごとの分布を密度プロットで比較してください