下巻 第4章 練習問題#
ここでは、 本書の学習内容の定着 を目的とした練習問題を掲載します。 解答・解説は「解答例」ページを参照してください。 なお、問題の性質上、本書で取り上げた処理と重複することがあります。 ご了承ください。
前提#
以下のように、ライブラリのインポートと変数の定義が完了していることを前提とします。
Show code cell content
# itertoolsモジュールのインポート
# 効率的なループを実行するためのイテレータビルディングブロックを提供
# これにより、データのコンビネーションや順列などを簡潔に表現できる
import itertools
# collectionsモジュールからOrderedDictのインポート
# OrderedDictは順序を保持する辞書型
from collections import OrderedDict
# 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のインポート
# より詳細なグラフ作成機能を利用可能
# goという名前で参照可能
import plotly.graph_objects as go
# plotly.graph_objectsからFigureクラスのインポート
# 型ヒントの利用を主目的とする
from plotly.graph_objects import Figure
# plotly.subplotsからmake_subplotsのインポート
# 複数のサブプロットを含む複合的な図を作成する際に使用
from plotly.subplots import make_subplots
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_CE = "cm_ce.csv"
# マンガ作品と原作者の対応関係に関するファイル
FN_CC_CRT = "cm_cc_crt.csv"
# アニメ各話に関するファイル
FN_AE = "an_ae.csv"
# アニメ作品と声優の対応関係に関するファイル
FN_AC_ACT = "an_ac_act.csv"
# ゲームパッケージとプラットフォームの対応関係に関するファイル
FN_PKG_PF = "gm_pkg_pf.csv"
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
# plotlyの描画設定の定義
# plotlyのグラフ描画用レンダラーの定義
# Jupyter Notebook環境のグラフ表示に適切なものを選択
RENDERER = "plotly_mimetype+notebook"
また、本書中で取り上げた以下の関数も、同様に利用可能とします。
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_jitter(values: pd.Series, scale: float = 0.3, seed: int = None) -> pd.Series:
"""
与えられた値にジッタリング(ランダムなノイズ)を適用する
Parameters
----------
values : pd.Series
ジッタリングを適用する数値が含まれるPandasのSeries
scale : float, optional
ランダムノイズの大きさを調整するためのスケール因子、デフォルトは0.3
seed : int, optional
乱数生成のためのシード値、指定された場合再現可能なランダムノイズが生成される
Returns
-------
pd.Series
ジッタリングが適用された数値を含むPandasのSeries
"""
# シード値が指定された場合は、乱数ジェネレータを初期化
if seed is not None:
np.random.seed(seed)
# ランダムなノイズを生成して値に加える
return values + np.random.randn(len(values)) * scale
Show code cell content
def create_connectedplot(
df: pd.DataFrame, x: str, y: str, text: str, color: str, **args
) -> Figure:
"""
データフレームから連結散布図を作成する
Parameters
----------
df : pd.DataFrame
グラフに使用するデータを含むpandasデータフレーム
x : str
x軸に使用するデータフレームの列名
y : str
y軸に使用するデータフレームの列名
text : str
プロット上で表示するテキストを含むデータフレームの列名
color : str
プロットのカラーマッピングに使用されるデータフレームの列名
カラーバーのタイトルとしても使用される
**args
追加のキーワード引数。これらはPlotly Express関数に渡される
Returns
-------
fig : plotly.graph_objs._figure.Figure
生成されたPlotlyのFigureオブジェクト
"""
# 折れ線グラフを使って連結散布図の基礎を作成する
fig_line = px.line(df, x=x, y=y, text=text, **args)
# 散布図を作成し、連結散布図のポイントとして折れ線グラフに追加する
fig_scatter = px.scatter(df, x=x, y=y, color=color, **args)
# 散布図のトレースを折れ線グラフに追加し、接続点を表現する
for trace in fig_scatter.data:
fig_line.add_trace(trace)
# 折れ線グラフのスタイルを更新し、視覚的特徴を強化する
fig_line.update_traces(
line={"color": "grey"},
marker={"size": 15, "line_width": 1, "opacity": 0.7},
textposition="bottom right",
)
# グラフのレイアウトを更新し、カラーバーのタイトルを`color`引数に基づいて設定する
fig_line.update_layout(coloraxis_colorbar=dict(title=color))
return fig_line
以下のようにデータを読みこんでいると仮定します。
Show 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:アニメの放送日数と各話数の関係#
関連セクション: 散布図
重複のあるデータに対して散布図を作成するとき、マーカーの透明度(opacity)を調整することで見やすくなることがあります。
そこで、opacityを あえて調整しない散布図 を作成することで、その効果を体感しましょう。
アニメ作品には、毎週1話ずつ放送されるものもあれば、1日に複数話が放送される特別編成のものもあります。 放送日数と各話数の関係を可視化することで、データの特性を把握できます。
df_ae(アニメ各話データ)を用いて、アニメ作品ごとの放送日数(ユニークな放送日の数)と各話数(ユニークな各話IDの数)の関係を散布図で可視化してください。
なお、マーカーのスタイルは size=10, line_width=1 とし、opacity は指定しないでください。
ヒント
作品ごとの集計は
groupbyとnunique()で行えます散布図は
px.scatter()で作成できますupdate_traces()でマーカーのスタイルを設定できます
基礎 問題2:年ごとのゲームパッケージ数#
関連セクション: 折れ線グラフ
折れ線グラフにおいて、各データ点にマーカーを表示するかどうかで印象が大きく変わります。 そこで本問では、 あえてマーカーを表示しない 設定とすることで、その影響を体験してみましょう。
ゲーム市場の動向を把握するために、年ごとのゲームパッケージ数の推移を可視化することは有用です。 折れ線グラフを用いることで、時系列データの変化を視覚的に捉えることができます。
df_pkg_pf(ゲームパッケージデータ)を用いて、年ごとのユニークな ゲームパッケージ数 の推移を折れ線グラフで可視化してください。
なお、mode="lines" を指定し、マーカーは表示しないでください。
ヒント
日付列を
pd.to_datetime()で変換し、.dt.yearで年を抽出できます年ごとの集計は
groupbyとnunique()で行えます折れ線グラフは
px.line()で作成できますupdate_traces(mode="lines")でマーカーなしに設定できます
標準 問題3:マンガ雑誌巻号の作品数と作者数の関係#
関連セクション: 散布図
散布図において、データ点が離散的な値を取る場合、同じ座標に複数の点が重なってしまう(オーバープロット)問題が発生します。 ジッタリング(微小なランダムノイズの付加)は、この問題を緩和する手法の一つです。
df_ce(マンガ各話データ)と df_cc_crt(マンガ作品×作者データ)を用いて、雑誌巻号ごとの 作品数 と 作者数 を集計し、ジッタリングを適用した散布図を作成してください。
ジッタリングには先に定義した add_jitter 関数を使用し、scale=1.0 を指定してください。
ヒント
雑誌巻号ごとの集計は
groupbyとnunique()で行えますジッタリングは
add_jitter(values, scale=1.0)で適用できます散布図は
px.scatter()で作成できます
標準 問題4:任天堂プラットフォームのパッケージ数推移#
関連セクション: 折れ線グラフ
折れ線グラフでは、データ点間をどのように補間するか(line_shape)によって、グラフの印象が大きく変わります。
線形補間(linear)、階段状補間(hv, vh)、スプライン曲線(spline)など、様々な補間方法があります。
df_pkg_pf(ゲームパッケージデータ)を用いて、任天堂プラットフォーム全体の年ごとのパッケージ数推移を、異なる line_shape(linear, hv, spline)で比較するサブプロットを作成してください。
ヒント
PF2MK辞書を使って任天堂のプラットフォームを特定できますmake_subplots()で複数のサブプロットを作成できますgo.Scatter()のline_shape引数で補間方法を指定できます
発展 問題5:アニメ放送枠の作品数と話数の関係#
関連セクション: 連結散布図
ある期間中のアニメの作品数と話数の関係は、その放送枠の性質(長期作品が多いか、短期作品の入れ替えが激しいか)を反映します。
df_ae(アニメ各話データ)を用いて、 「平日放送のみの作品群」と「土日放送のみの作品群」 で、作品数と話数のバランスがどう異なるかを、連結散布図で可視化してください。
ヒント
土日判定は
.dt.weekday >= 5で行えます作品ごとの曜日種別数は
groupbyとnunique()で確認できます連結散布図は
create_connectedplot()関数で作成できますファセット分割は
facet_col引数で指定します
応用 問題6:マンガ掲載位置の遷移#
関連セクション: 等値線図
マンガ雑誌において、ある作品の「現在の掲載位置」が「次号の掲載位置」にどの程度影響するかは、連載の安定性を測る指標の一つです。掲載順が固定されていればデータ点は直線 \(y=x\) 付近に集中し、変動が激しければ分散します。
df_ce(マンガ各話データ)を用いて、連載初期から中盤にかけてこの遷移傾向がどう変化するかを等値線図で可視化しましょう。
横軸に現在の掲載位置、縦軸に次話の掲載位置を取り、話数レンジ(1-10話、11-20話、21-30話、31-40話)ごとにファセットをわけてください。
ヒント
「次話の掲載位置」は
groupbyとshift(-1)で算出できます作品内の話数インデックスは
cumcount()で付与できます等値線図は
px.density_contour()で作成できますcontours_coloring="fill"で密度に応じた塗り分けができます
応用 問題7:経過年によるパッケージ数の推移#
関連セクション: 折れ線グラフ
ゲームプラットフォームには、発売から普及、そして衰退までのライフサイクルがあります。 西暦ではなく、 発売からの経過年 を軸に据えることで、異なる世代のプラットフォーム同士を同じ基準で比較できます。
df_pkg_pf(ゲームパッケージデータ)を用いて、歴代の「プレイステーション」シリーズを対象に、発売から何年目に最も多くのソフト(パッケージ数)が供給されたかを折れ線グラフで可視化してみましょう。
ヒント
文字列フィルタリングは
str.contains()で行えます経過年インデックスは
groupbyとcumcount()で算出できます折れ線グラフは
px.line()で作成できますmode="lines+markers"で線とマーカーの両方を表示できます