下巻 第3章 練習問題#
ここでは、 本書の学習内容の定着 を目的とした練習問題を掲載します。 解答・解説は「解答例」ページを参照してください。 なお、問題の性質上、本書で取り上げた処理と重複することがあります。 ご了承ください。
前提#
以下のように、ライブラリのインポートと変数の定義が完了していることを前提とします。
Show code cell content
# itertoolsモジュールのインポート
# 効率的なループを実行するためのイテレータビルディングブロックを提供
# これにより、データのコンビネーションや順列などを簡潔に表現できる
import itertools
# 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.graph_objectsからFigureクラスのインポート
# 型ヒントの利用を主目的とする
from plotly.graph_objects import Figure
Show code cell content
# マンガデータ保存ディレクトリのパス
DIR_CM = Path("../../../data/cm/input")
# アニメデータ保存ディレクトリのパス
DIR_AN = Path("../../../data/an/input")
# ゲームデータ保存ディレクトリのパス
DIR_GM = Path("../../../data/gm/input")
Show code cell content
# 読み込み対象ファイル名の定義
# マンガ作品とマンガ作者の対応関係に関するファイル
FN_CC_CRT = "cm_cc_crt.csv"
# マンガ各話に関するファイル
FN_CE = "cm_ce.csv"
# アニメ作品と原作者の対応関係に関するファイル
FN_AC_ACT = "an_ac_act.csv"
# アニメ各話に関するファイル
FN_AE = "an_ae.csv"
# ゲームパッケージとプラットフォームの対応関係に関するファイル
FN_PKG_PF = "gm_pkg_pf.csv"
Show code cell content
# 可視化に関する設定値の定義
# 「年代」の集計単位
UNIT_YEARS = 10
# plotlyの描画設定の定義
# plotlyのグラフ描画用レンダラーの定義
# Jupyter Notebook環境のグラフ表示に適切なものを選択
RENDERER = "plotly_mimetype+notebook"
Show code cell content
# 質的変数の描画用のカラースケールの定義
# 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 content
# 国内主要ゲームメーカーのプラットフォームとメーカー名の対応辞書
# キー: プラットフォーム名、値: メーカー名の略称
PF2MK = {
"プレイステーション": "ソニー",
"プレイステーション2": "ソニー",
"プレイステーション・ポータブル": "ソニー",
"プレイステーション3": "ソニー",
"プレイステーションVita": "ソニー",
"プレイステーション4": "ソニー",
"ゲームアーカイブス": "ソニー",
"SG-1000": "セガ",
"SC-3000": "セガ",
"SEGAマーク3": "セガ",
"セガ・マスターシステム": "セガ",
"メガドライブ": "セガ",
"ゲームギア": "セガ",
"セガサターン": "セガ",
"ドリームキャスト": "セガ",
"ファミリーコンピュータ": "任天堂",
"ゲームボーイ": "任天堂",
"スーパーファミコン": "任天堂",
"NINTENDO64": "任天堂",
"ゲームボーイアドバンス": "任天堂",
"ニンテンドーゲームキューブ": "任天堂",
"ニンテンドーDS": "任天堂",
"ニンテンドー3DS": "任天堂",
"Wii": "任天堂",
"WiiU": "任天堂",
"NintendoSwitch": "任天堂",
}
Show code cell content
# pandasのweekday関数で取得できる曜日の数値と実際の曜日名を対応させる辞書を定義
# 0:月曜日, 1:火曜日, ... , 6:日曜日
WEEKDAY2YOBI = {
0: "月",
1: "火",
2: "水",
3: "木",
4: "金",
5: "土",
6: "日",
}
また、本書中で取り上げた以下の関数も、同様に利用可能とします。
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 add_years_to_df(
df: pd.DataFrame, unit_years: int = UNIT_YEARS, col_date: str = "date"
) -> pd.DataFrame:
"""
データフレームにunit_years単位で区切った年数を示す新しい列を追加
Parameters
----------
df : pd.DataFrame
入力データフレーム
unit_years : int, optional
年数を区切る単位、デフォルトはUNIT_YEARS
col_date : str, optional
日付を含むカラム名、デフォルトは "date"
Returns
-------
pd.DataFrame
新しい列が追加されたデータフレーム
"""
# 入力データフレームをコピー
df_new = df.copy()
# unit_years単位で年数を区切り、新しい列として追加
df_new["years"] = (
pd.to_datetime(df_new[col_date]).dt.year // unit_years * unit_years
)
# 'years'列のデータ型を文字列に変更
df_new["years"] = df_new["years"].astype(str)
return df_new
また、以下のようにデータを読み込み済みと仮定します。
Show code cell content
# 各種データの読み込み
df_ce = pd.read_csv(DIR_CM / FN_CE) # マンガ各話に関するデータ
df_cc_crt = pd.read_csv(DIR_CM / FN_CC_CRT) # マンガ作品と作者の対応データ
df_ae = pd.read_csv(DIR_AN / FN_AE) # アニメ各話に関するデータ
df_ac_act = pd.read_csv(DIR_AN / FN_AC_ACT) # アニメ作品と声優の対応データ
df_pkg_pf = pd.read_csv(
DIR_GM / FN_PKG_PF
) # ゲームパッケージとプラットフォームの対応データ
基礎 問題1:年代別・曜日別のゲームパッケージ数#
関連セクション: 円グラフ
本書では、年代別に発売曜日ごとのゲームパッケージ数を円グラフで可視化し、category_ordersを指定して曜日順(月〜日)に並べました。
ここでは、category_ordersを指定しない場合にどのようなグラフになるか確認してみましょう。
df_pkg_pfを用いて、1990年代以降の年代別(5年刻み)・曜日別のゲームパッケージ数を、ファセット分割した円グラフで可視化してください。ただし、
category_ordersは 指定しない でください。
ヒント
年代情報は
add_years_to_df(df, unit_years=5)で5年単位の年代を追加できます曜日は
.dt.weekdayで取得し、WEEKDAY2YOBI辞書で日本語に変換できますファセット分割は
facet_col引数で指定します
基礎 問題2:性別ごとの声優数の推移#
関連セクション: 積上げ密度プロット
アニメ作品に出演する声優の性別[1]比率は、時代によって変化があるのでしょうか。
df_aeとdf_ac_actを用いて、2005年以降の放送年ごとの性別別声優数を集計し、積上げ密度プロット(px.area)で可視化してください。
ヒント
df_ac_actとdf_aeをacidをキーにマージします放送年は
add_years_to_df(df, unit_years=1)で1年単位の年情報を追加できます積上げ密度プロットは
px.area()で作成できます
標準 問題3:週刊少年マガジンの年代別作者数#
関連セクション: 円グラフ
本文では四大少年誌全体のマンガ作者数を年代別に可視化しました。 ここでは、週刊少年マガジンのみに絞り込んで、年代別のマンガ作者数を円グラフで可視化してください。
df_ceとdf_cc_crtを用いて、週刊少年マガジンに掲載されたマンガ作者の年代別内訳を示す円グラフを作成しましょう。
その際、以下の点に注意してください:
category_ordersを指定して、年代順(1970, 1980, …)に並べる年代は 順序のある質的変数 なので、
px.colors.diverging.Portlandパレットを使用する
ヒント
df_cc_crtをmcname == "週刊少年マガジン"でフィルタリングします年代情報は
add_years_to_df()で追加できますdf_ceとdf_cc_crtをccidでマージして年代情報を取得します年代の順序リストは
["1970", "1980", "1990", "2000", "2010"]のようになります
標準 問題4:プレイステーションシリーズの発売数推移#
関連セクション: 積上げ棒グラフ
ソニー[2]のプレイステーションシリーズは、世代を重ねるごとに新しいプラットフォームが登場してきました。
df_pkg_pfを用いて、プレイステーションシリーズ(プラットフォーム名が「プレイステーション」で始まるもの)に絞り込み、発売年ごとのプラットフォーム別パッケージ数を積上げ棒グラフで可視化してください。
色でプラットフォームを区別し、各プラットフォームの発売数推移を確認しましょう。
ヒント
str.startswith("プレイステーション")でプラットフォーム名をフィルタリングできます発売年は
.dt.yearで取得できます積上げ棒グラフは
px.bar()でbarmode="stack"を指定しますプラットフォームごとに色を分けるには
color引数を使用します
発展 問題5:第1話・最終話のカラー獲得率#
関連セクション: 積上げ棒グラフ
新連載の第1話は、読者の目を引くために巻頭カラーやセンターカラーで華々しく飾られることが一般的です。
一方で、連載の最後を飾る最終話の扱いは、雑誌の編集方針や作品の評価によって分かれるかもしれません。
合計話数が8以上の連載作品を対象に、各作品の「最初の一話」と「最後の一話」を抽出し、それぞれのカラー掲載率(four_colored[3])を比較しましょう。
横軸に率(合計を1として標準化)、縦軸にマンガ雑誌名を並べた積み上げ横棒グラフを作成してください。
その際、最初の一話か最後の一話かをファセット(facet_col)で分けて表示しましょう。
ヒント
作品ごとの合計話数は
groupbyとsize()で集計できます最初と最後の行は
idxmin()/idxmax()で特定できます積み上げ棒グラフは
px.bar()でbarmode="stack"を指定しますファセット分割は
facet_col引数で指定します
応用 問題6:曜日別・メーカー別の発売数推移#
関連セクション: 積上げ棒グラフ
ゲームパッケージの発売曜日は、時代とともに変遷してきました。
先に定義したPF2MK辞書を用いてメーカー情報を付与し、メーカーごとにファセット(サブプロット)を分割して、発売年ごとの曜日内訳を積上げ棒グラフで可視化してください。
ヒント
発売曜日は
.dt.weekdayで取得し、WEEKDAY2YOBI辞書で変換できます辞書によるマッピングは
.map()メソッドを使用しますファセット分割は
facet_colとfacet_col_wrapで制御できますcategory_ordersで曜日の表示順序を指定できます
応用 問題7:アニメ話数の推移#
関連セクション: 積上げ密度プロット
本書で何度か触れたように、1990年代後半からアニメ作品の短尺化が進んだ可能性があります。
そこで、作品あたりの合計話数が 13 話以下のものを「1クール」、それ以外を「その他」と分類し、
放送年ごとの作品数の内訳を、積上げ密度プロット(px.area、エリアチャート)で表現してください。
分類にはdf_aeを用い、1995年前後で構成がどのように変化したか観察しましょう。
ヒント
作品ごとの合計話数は
groupbyとsize()で集計できます条件に応じたラベル付けは
applyとlambdaで実装できます積上げ密度プロットは
px.area()で作成できますhovermode="x unified"で同一x座標の値を同時に表示できます