棒グラフ#
準備#
Import#
Show code cell content
# warningsモジュールのインポート
import warnings
# データ解析や機械学習のライブラリ使用時の警告を非表示にする目的で警告を無視
# 本書の文脈では、可視化の学習に議論を集中させるために選択した
# ただし、学習以外の場面で、警告を無視する設定は推奨しない
warnings.filterwarnings("ignore")
Show 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.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")
# マンガデータの分析結果の出力先ディレクトリのパス
DIR_OUT_CM = (
DIR_CM.parent / "output" / Path.cwd().parts[-2] / Path.cwd().parts[-1] / "bar"
)
# アニメデータの分析結果の出力先ディレクトリのパス
DIR_OUT_AN = (
DIR_AN.parent / "output" / Path.cwd().parts[-2] / Path.cwd().parts[-1] / "bar"
)
# ゲームデータの分析結果の出力先ディレクトリのパス
DIR_OUT_GM = (
DIR_GM.parent / "output" / Path.cwd().parts[-2] / Path.cwd().parts[-1] / "bar"
)
Show code cell content
# 読み込み対象ファイル名の定義
# Comic CollectionとCReaTor関連のファイル名
FN_CC_CRT = "cm_cc_crt.csv"
# Anime Episode関連のファイル名
FN_AE = "an_ae.csv"
# PacKaGeとPlatForm関連のファイル名
FN_PKG_PF = "gm_pkg_pf.csv"
Show code cell content
# 可視化に関する設定値の定義
# 可視化対象のマンガ作者数
N_CRT = 20
# 可視化対象のアニメ作品数
N_AC = 20
# 可視化対象のゲームプラットフォーム数
N_PF = 20
Show code cell content
# 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 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 save_df_to_csv(df: pd.DataFrame, dir_save: Path, fn_save: str) -> None:
"""
DataFrameをCSVファイルとして指定されたディレクトリに保存する関数
Parameters
----------
df : pd.DataFrame
保存対象となるDataFrame
dir_save : Path
出力先ディレクトリのパス
fn_save : str
保存するCSVファイルの名前(拡張子は含めない)
"""
# 出力先ディレクトリが存在しない場合は作成
dir_save.mkdir(parents=True, exist_ok=True)
# 出力先のパスを作成
p_save = dir_save / f"{fn_save}.csv"
# DataFrameをCSVファイルとして保存する
df.to_csv(p_save, index=False, encoding="utf-8-sig")
# 保存完了のメッセージを表示する
print(f"DataFrame is saved as '{p_save}'.")
Show code cell content
def format_cols(df: pd.DataFrame, cols_rename: Dict[str, str]) -> pd.DataFrame:
"""
指定されたカラムのみをデータフレームから抽出し、カラム名をリネームする関数
Parameters
----------
df : pd.DataFrame
入力データフレーム
cols_rename : Dict[str, str]
リネームしたいカラム名のマッピング(元のカラム名: 新しいカラム名)
Returns
-------
pd.DataFrame
カラムが抽出・リネームされたデータフレーム
"""
# 指定されたカラムのみを抽出し、リネーム
df = df[cols_rename.keys()].rename(columns=cols_rename)
return df
可視化例#
マンガデータ#
Show code cell content
# pandasのread_csv関数でCSVファイルの読み込み
df_cc_crt = pd.read_csv(DIR_CM / FN_CC_CRT)
Show code cell content
# 'crtname'を基に'n_ce'の合計を計算
df_cm = df_cc_crt.groupby("crtname")["n_ce"].sum().reset_index()
# 'n_ce'で降順ソートし、上位N_CRT件を選択
df_cm = df_cm.sort_values("n_ce", ascending=False, ignore_index=True).head(N_CRT)
# 描画に適したカラム名に変更
df_cm = df_cm.rename(columns={"crtname": "マンガ作者名", "n_ce": "合計話数"})
Show code cell content
# 可視化手法のDataFrameを確認
df_cm.head()
| マンガ作者名 | 合計話数 | |
|---|---|---|
| 0 | 水島新司 | 2798 |
| 1 | 秋本治 | 1979 |
| 2 | 梶原一騎 | 1873 |
| 3 | 高橋留美子 | 1736 |
| 4 | 浜岡賢次 | 1384 |
Show code cell content
# 可視化対象DataFrameを保存
save_df_to_csv(df_cm, DIR_OUT_CM, "cm")
DataFrame is saved as '../../../data/cm/output/vol2/01/bar/cm.csv'.
Show code cell source
# plotly.expressのbar関数で棒グラフ作成
# x軸: 'マンガ作者名', y軸: '合計話数'
fig = px.bar(df_cm, x="マンガ作者名", y="合計話数")
# 先に定義したshow_fig関数でグラフ表示
show_fig(fig)
Show code cell source
# '作者名'のアルファベット順でソートし棒グラフを作成
# x軸: 'マンガ作者名', y軸: '合計話数'
fig = px.bar(df_cm.sort_values("マンガ作者名"), x="マンガ作者名", y="合計話数")
# show_fig関数でグラフ表示
show_fig(fig)
アニメデータ#
Show code cell content
# pandasのread_csv関数でCSVファイルをデータフレームとして読み込み
df_ae = pd.read_csv(DIR_AN / FN_AE)
Show code cell content
# 'acname' を基準にグループ化し、'aeid' のユニークな値の数を計算
# 各アニメ作品の合計話数を取得
df_an = df_ae.groupby("acname")["aeid"].nunique().reset_index(name="n_ae")
# 'n_ae' の値で降順ソートし、上位 N_AC 件をデータ取得
df_an = df_an.sort_values("n_ae", ascending=False, ignore_index=True).head(N_AC)
# 可視化用にカラム名を変更
df_an = df_an.rename(columns={"acname": "アニメ作品名", "n_ae": "合計話数"})
Show code cell content
# 可視化対象のDataFrameを確認
df_an.head()
| アニメ作品名 | 合計話数 | |
|---|---|---|
| 0 | クレヨンしんちゃん | 1926 |
| 1 | 親子クラブ | 1363 |
| 2 | サザエさん | 1175 |
| 3 | ちびまる子ちゃん[新] | 994 |
| 4 | それいけ!アンパンマン | 958 |
Show code cell content
# 可視化対象DataFrameを保存
save_df_to_csv(df_an, DIR_OUT_AN, "an")
DataFrame is saved as '../../../data/an/output/vol2/01/bar/an.csv'.
Show code cell source
# plotly.expressのbar関数で棒グラフを作成
# x軸は'アニメ作品名'、y軸は'合計話数'
fig = px.bar(df_an, x="アニメ作品名", y="合計話数")
# show_fig関数で棒グラフを表示
show_fig(fig)
Show code cell source
# 横棒グラフの可視化
# plotly.expressのbar関数で横棒グラフ作成
# y軸は'アニメ作品名'、x軸は'合計話数'、'orientation="h"'で「横向き」を指定
# グラフの高さを500ピクセルに指定することで全件余裕を持って表示
fig = px.bar(df_an, y="アニメ作品名", x="合計話数", orientation="h", height=500)
# show_fig関数で図を表示
show_fig(fig)
Show code cell content
# 'acname'毎の'aeid'の数と'date'の最初・最後の日付集計
df_tmp = (
df_ae.groupby("acname")
.agg(n_ae=("aeid", "nunique"), start_date=("date", "min"), end_date=("date", "max"))
.reset_index()
)
# 'acname'に「ドラえもん」を含むデータの抽出
df_tmp[df_tmp["acname"].str.contains("ドラえもん")]
| acname | n_ae | start_date | end_date | |
|---|---|---|---|---|
| 1914 | ドラえもん[新・第2期] | 608 | 2005-04-15 | 2016-12-31 |
| 1915 | ドラえもん[新] | 224 | 1999-12-03 | 2005-03-18 |
Show code cell content
# 'acname'に「ちびまる子ちゃん」を含むデータの抽出
df_tmp[df_tmp["acname"].str.contains("ちびまる子ちゃん")]
| acname | n_ae | start_date | end_date | |
|---|---|---|---|---|
| 1029 | ちびまる子ちゃん[新] | 994 | 1999-12-05 | 2016-12-25 |
Show code cell content
# df_aeデータフレームを'date'列で昇順に並び替えて、'asid'でグループ化
# 各グループにおける'aeid'のユニークな値の数と、最初の'acname'を集計
# acnameを用いるのは、asname相当のデータが存在しないため
df_an2 = (
df_ae.sort_values("date")
.groupby("asid")
.agg({"aeid": "nunique", "acname": "first"})
).reset_index()
# 集計したデータフレームdf_an2を'aeid'(つまりシリーズ合計話数)で降順に並び替え、
# 上位N_AC件を取得して新たなdf_an2に更新
# ignore_index=Trueにより、インデックスを新しい連番にリセット
df_an2 = df_an2.sort_values("aeid", ascending=False, ignore_index=True).head(N_AC)
# 列名をより分かりやすい名称に変更
df_an2 = df_an2.rename(
columns={
"acname": "代表的なアニメ作品名",
"aeid": "シリーズ合計話数",
"asid": "アニメシリーズID",
}
)
Show code cell content
# 可視化対象とするDataFrameを確認
df_an2.head()
| アニメシリーズID | シリーズ合計話数 | 代表的なアニメ作品名 | |
|---|---|---|---|
| 0 | C1462 | 2084 | 忍たま 乱太郎[第1期] |
| 1 | C1327 | 1926 | クレヨンしんちゃん |
| 2 | C2158 | 1653 | おじゃる丸 |
| 3 | C1640 | 1363 | 親子クラブ |
| 4 | C4102 | 1245 | いない いない ばあっ![第4期] |
Show code cell content
# 可視化対象DataFrameを保存
save_df_to_csv(df_an2, DIR_OUT_AN, "an2")
DataFrame is saved as '../../../data/an/output/vol2/01/bar/an2.csv'.
Show code cell source
# 横棒グラフの可視化
# plotly.expressのbar関数で横棒グラフ作成
# y軸は'アニメ作品名'、x軸は'合計話数'、'orientation="h"'で「横向き」を指定
# グラフの高さを500ピクセルに指定することで全件余裕を持って表示
fig = px.bar(
df_an2, y="代表的なアニメ作品名", x="シリーズ合計話数", orientation="h", height=500
)
# show_fig関数で図を表示
show_fig(fig)
ゲームデータ#
Show code cell content
# pandasのread_csv関数でCSVファイルをデータフレームとして読み込み
df_pkg_pf = pd.read_csv(DIR_GM / FN_PKG_PF)
Show code cell content
# 'pfname'に基づき、'pkgid'のユニークな値の数の集計
df_gm = df_pkg_pf.groupby("pfname")["pkgid"].nunique().reset_index(name="n_pkg")
# 'n_pkg'の値で降順ソートし、上位N_PF件のデータを取得
df_gm = df_gm.sort_values("n_pkg", ascending=False).head(N_PF)
# カラム名を可視化に適したものに変更
df_gm = df_gm.rename(columns={"pfname": "プラットフォーム名", "n_pkg": "パッケージ数"})
Show code cell content
# 可視化対象とするDataFrameを確認
df_gm.head()
| プラットフォーム名 | パッケージ数 | |
|---|---|---|
| 40 | プレイステーション2 | 4216 |
| 39 | プレイステーション | 3750 |
| 44 | プレイステーション・ポータブル | 3417 |
| 41 | プレイステーション3 | 2501 |
| 43 | プレイステーションVita | 2348 |
Show code cell content
# 可視化対象DataFrameを保存
save_df_to_csv(df_gm, DIR_OUT_GM, "gm")
DataFrame is saved as '../../../data/gm/output/vol2/01/bar/gm.csv'.
Show code cell source
# plotly.expressのbar関数で棒グラフの作成
# x軸: プラットフォーム名、y軸: パッケージ数
fig = px.bar(df_gm, x="プラットフォーム名", y="パッケージ数")
# show_fig関数で図の表示
show_fig(fig)
Show code cell content
# ゲームのプラットフォームとメーカーの対応辞書
# キー: プラットフォーム名、値: メーカー名の略称
pf2mk = {
"プレイステーション2": "ソニー",
"プレイステーション": "ソニー",
"プレイステーション・ポータブル": "ソニー",
"プレイステーション3": "ソニー",
"プレイステーションVita": "ソニー",
"ニンテンドー3DS": "任天堂",
"ニンテンドーDS": "任天堂",
"プレイステーション4": "ソニー",
"Xbox360": "マイクロソフト",
"Wii": "任天堂",
"スーパーファミコン": "任天堂",
"ゲームアーカイブス": "ソニー",
"ゲームボーイ": "任天堂",
"セガサターン": "セガ",
"WiiU": "任天堂",
"XboxOne": "マイクロソフト",
"ゲームボーイアドバンス": "任天堂",
"MicrosoftWindows": "マイクロソフト",
"ドリームキャスト": "セガ",
"メガドライブ": "セガ",
}
Show code cell content
# 可視化用に新たなDataFrameを作成
df_gm2 = df_gm.copy()
# 'プラットフォーム名'をキーとして辞書'pf2mk'からメーカー名を取得
# 新たな'メーカー名'カラムに格納
df_gm2["メーカー名"] = df_gm2["プラットフォーム名"].map(pf2mk)
Show code cell content
# 可視化対象とするDataFrameを確認
df_gm2.head()
| プラットフォーム名 | パッケージ数 | メーカー名 | |
|---|---|---|---|
| 40 | プレイステーション2 | 4216 | ソニー |
| 39 | プレイステーション | 3750 | ソニー |
| 44 | プレイステーション・ポータブル | 3417 | ソニー |
| 41 | プレイステーション3 | 2501 | ソニー |
| 43 | プレイステーションVita | 2348 | ソニー |
Show code cell content
# 可視化対象DataFrameを保存
save_df_to_csv(df_gm2, DIR_OUT_GM, "gm2")
DataFrame is saved as '../../../data/gm/output/vol2/01/bar/gm2.csv'.
Show code cell source
# 'プラットフォーム名'をx軸、'パッケージ数'をy軸として棒グラフ作成
# カラーは'メーカー名'に基づき、カラーパレットにはOKABE_ITOを使用
fig = px.bar(
df_gm2,
x="プラットフォーム名",
y="パッケージ数",
color="メーカー名",
height=400,
color_discrete_sequence=OKABE_ITO,
)
# show_fig関数で図の表示
show_fig(fig)
Show code cell source
# 'パッケージ数'をx軸'プラットフォーム名'をy軸、として横棒グラフ作成
# カラーは'メーカー名'に基づき、カラーパレットにはOKABE_ITOを使用
fig = px.bar(
df_gm2,
x="パッケージ数",
y="プラットフォーム名",
color="メーカー名",
orientation="h",
height=400,
color_discrete_sequence=OKABE_ITO,
)
# show_fig関数で図の表示
show_fig(fig)
Show code cell source
# 'update_layout'でグラフの凡例の位置を調整
# 凡例の右上の角を図の右上に固定 (x=0.99, y=0.99)
fig.update_layout(legend=dict(yanchor="top", y=0.99, xanchor="right", x=0.99))
# show_fig関数で図の表示
show_fig(fig)