メディア展開データの基礎分析#

準備#

Import#

Hide code cell content
# warningsモジュールのインポート
import warnings

# データ解析や機械学習のライブラリ使用時の警告を非表示にする目的で警告を無視
# 本書の文脈では、可視化の学習に議論を集中させるために選択した
# ただし、学習以外の場面で、警告を無視する設定は推奨しない
warnings.filterwarnings("ignore")
Hide code cell content
# difflibモジュールのインポート
# 文字列間の類似度や差異を計算するためのユーティリティを提供
import difflib

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

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

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

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

# tqdm_notebookのインポート
# Jupyter Notebook環境でのプログレスバー表示に使用
# tqdmという名前で参照可能
from tqdm import tqdm_notebook as tqdm

変数#

Hide code cell content
# 読み込み対象ディレクトリの定義

# メディア展開データが保存されているディレクトリのパス
DIR_IN = Path("../../../data/mix/input")
Hide code cell content
# 読み込み対象ファイル名の定義

# アニメ各話と原作マンガの作者者の対応関係に関するファイル
FN_AE_CRT = "mix_ae_crt.csv"

# マンガ各話とアニメ作品の対応関係に関するファイル
FN_CE_AC = "mix_ce_ac.csv"

関数#

Hide code cell content
def find_closest_match(row: pd.Series, df: pd.DataFrame) -> Optional[str]:
    """
    DataFrameの行に対して、指定されたアニメ作品名(`acname`)に最も近いマンガ作品名(`ccname`)を見つける
    ただし、`acname`がNaNの行は処理をスキップする

    Parameters
    ----------
    row : pd.Series
        処理するDataFrameの行。各行はアニメ作品名(`acname`)を含む
    df : pd.DataFrame
        検索対象のマンガ作品名(`ccname`)を含むDataFrame

    Returns
    -------
    Optional[str]
        最も類似度が高いマンガ作品名
        ただし、`acname`がNaNの場合はNoneを返す
    """
    # acnameがNaNの場合は処理をスキップ
    if pd.isna(row["acname"]):
        return None

    # acnameに最も近いccnameを返す
    closest_matches = difflib.get_close_matches(
        row["acname"], df["ccname"], n=1, cutoff=0.0
    )
    return closest_matches[0] if closest_matches else None

mix_ae_crt.csvの基礎分析#

Hide code cell content
# pandasのread_csv関数でCSVファイルの読み込み
df_ae_crt = pd.read_csv(DIR_IN / FN_AE_CRT)

全体像の把握#

Hide code cell content
# df_ae_crtデータフレームの先頭5行をTで転置して表示
# 列が一定以上あるとき、転置すると見やすくなることがある
df_ae_crt.head().T
0 1 2 3 4
aeid M53249 M53250 M53251 M53252 M53253
aename 共 振 バイブレーション 発 動 トランス 悪 夢 ナイトメア 迎 撃 インターセプト 反 撃 カウンターアタック
date 2001-04-08 2001-04-15 2001-04-22 2001-04-29 2001-05-06
aeno 1 2 3 4 5
acid C10003 C10003 C10003 C10003 C10003
acname PROJECT ARMS PROJECT ARMS PROJECT ARMS PROJECT ARMS PROJECT ARMS
asid C2484 C2484 C2484 C2484 C2484
n_ae 26 26 26 26 26
first_date 2001-04-08 2001-04-08 2001-04-08 2001-04-08 2001-04-08
last_date 2001-09-30 2001-09-30 2001-09-30 2001-09-30 2001-09-30
ccid C92062 C92062 C92062 C92062 C92062
crtid CCRT02576 CCRT02576 CCRT02576 CCRT02576 CCRT02576
ccname ARMS ARMS ARMS ARMS ARMS
mcname 週刊少年サンデー 週刊少年サンデー 週刊少年サンデー 週刊少年サンデー 週刊少年サンデー
crtname 皆川亮二 皆川亮二 皆川亮二 皆川亮二 皆川亮二
Hide code cell content
# df_ae_crtデータフレームの形状(行数・列数)を取得
# shape属性を使用すると、(行数, 列数)の形で結果が返される
df_ae_crt.shape
(12700, 15)
Hide code cell content
# df_ae_crtデータフレーム内の欠損値(NaN)の情報を集計
# isna()メソッドを使用して欠損値の場所をTrueとして特定
# その後、agg()メソッドを使用して、各列における欠損値の合計と平均を計算しTで転置
df_ae_crt.isna().agg([sum, "mean"]).T
sum mean
aeid 0.0 0.000000
aename 26.0 0.002047
date 0.0 0.000000
aeno 104.0 0.008189
acid 0.0 0.000000
acname 0.0 0.000000
asid 0.0 0.000000
n_ae 0.0 0.000000
first_date 0.0 0.000000
last_date 0.0 0.000000
ccid 0.0 0.000000
crtid 0.0 0.000000
ccname 0.0 0.000000
mcname 0.0 0.000000
crtname 0.0 0.000000
Hide code cell content
# df_ae_crtデータフレームの記述統計情報を取得
# describe()メソッドを使用して、各列の基本的な統計量を表示
df_ae_crt.describe()
n_ae
count 12700.000000
mean 184.338110
std 236.538762
min 1.000000
25% 30.000000
50% 75.000000
75% 198.000000
max 783.000000
Hide code cell content
# df_ae_crtデータフレームの各列に対してユニークな値の数をカウント
# nunique()メソッドを使用して、各列のユニークな値の数を計算
# その後、結果を新しいデータフレームとして整形し、列名を`nunique`とする
df_ae_crt.nunique().reset_index(name="nunique")
index nunique
0 aeid 11407
1 aename 11315
2 date 5926
3 aeno 1076
4 acid 238
5 acname 238
6 asid 152
7 n_ae 75
8 first_date 214
9 last_date 216
10 ccid 157
11 crtid 154
12 ccname 157
13 mcname 4
14 crtname 154
Hide code cell content
# `aeid`と`crtid`の組み合わせで重複する行がないことを確認
assert df_ae_crt.duplicated(subset=["aeid", "crtid"]).sum() == 0

date列の深掘り#

Hide code cell content
# df_ae_crtデータフレームの`date`列から最も古い日付と最も新しい日付を取得
# min()メソッドを使用して、最も古い日付を抽出
# max()メソッドを使用して、最も新しい日付を抽出
df_ae_crt["date"].min(), df_ae_crt["date"].max()
('1990-01-14', '2017-09-30')
Hide code cell content
# `date`列を日付型に変換
# pd.to_datetime()メソッドを使用して、文字列型の日付を日付型(datetime)に変換
df_ae_crt["date"] = pd.to_datetime(df_ae_crt["date"])

# 年に関する情報を新しい`year`列として追加
# dt.yearを使用して、日付から年のみを取得
df_ae_crt["year"] = df_ae_crt["date"].dt.year

# 月に関する情報を新しい`month`列として追加
# dt.monthを使用して、日付から月のみを取得
df_ae_crt["month"] = df_ae_crt["date"].dt.month

# 曜日に関する情報を新しい`weekday`列として追加
# dt.weekdayを使用して、日付から曜日の情報を数値(0:月曜日, 6:日曜日)として取得
df_ae_crt["weekday"] = df_ae_crt["date"].dt.weekday
Hide code cell content
# `year`(年)ごとに各カラムのユニークな値の数を集計
# 具体的には、groupbyメソッドで`year`を基準にグループ化し、
# nuniqueメソッドを使用して各カラムのユニークな値の数を計算
# その後、reset_indexメソッドでインデックスをリセットし、データフレームとして結果を返す
df_ae_crt.groupby("year")[["month", "asid", "acid", "aeid"]].nunique().reset_index()
year month asid acid aeid
0 1990 5 3 3 41
1 1991 12 6 6 158
2 1992 12 4 4 102
3 1993 12 6 6 153
4 1994 12 9 9 257
5 1995 12 5 5 143
6 1996 12 6 6 136
7 1997 12 8 8 186
8 1998 12 11 11 316
9 1999 12 12 12 223
10 2000 12 15 15 410
11 2001 12 19 21 528
12 2002 12 20 20 622
13 2003 12 17 17 521
14 2004 12 21 22 565
15 2005 12 23 24 650
16 2006 12 28 31 672
17 2007 12 23 26 652
18 2008 12 18 19 481
19 2009 12 17 17 542
20 2010 12 20 21 510
21 2011 12 19 21 550
22 2012 12 18 21 537
23 2013 12 21 22 462
24 2014 12 22 24 611
25 2015 12 23 26 697
26 2016 12 23 24 509
27 2017 9 7 7 173
Hide code cell content
# `weekday`(曜日)ごとに各カラムのユニークな値の数を集計
# 具体的には、groupbyメソッドで`weekday`を基準にグループ化し、
# nuniqueメソッドを使用して各カラムのユニークな値の数を計算
# その後、reset_indexメソッドでインデックスをリセットし、データフレームとして結果を返す
df_ae_crt.groupby("weekday")[["asid", "acid", "aeid"]].nunique().reset_index()
weekday asid acid aeid
0 0 26 32 1289
1 1 37 45 1323
2 2 35 39 1581
3 3 26 30 1213
4 4 29 33 446
5 5 49 68 2510
6 6 53 72 3045

aeidaenameaeno列の深掘り#

Hide code cell content
# 原作マンガの属するマンガ雑誌ごとに、アニメ各話数を集計
df_ae_crt.groupby("mcname")["aeid"].nunique().reset_index(name="n_ae")
mcname n_ae
0 週刊少年サンデー 2655
1 週刊少年ジャンプ 6393
2 週刊少年チャンピオン 433
3 週刊少年マガジン 1926
Hide code cell content
# atsname(Anime Time Slot NAME)としてacidとdateを結合した文字列を追加
df_ae_crt["atsname"] = df_ae_crt["acid"] + "_" + df_ae_crt["date"].astype(str)
# mcnameごとにユニークなアニメ放送枠数を集計
df_ae_crt.groupby("mcname")["atsname"].nunique().reset_index(name="n_ats")
mcname n_ats
0 週刊少年サンデー 2580
1 週刊少年ジャンプ 6188
2 週刊少年チャンピオン 417
3 週刊少年マガジン 1838
Hide code cell content
# aename列の文字列の長さを算出し、l_aename列として格納
df_ae_crt["l_aename"] = df_ae_crt["aename"].str.len()
Hide code cell content
# l_aename列の統計量を算出
df_ae_crt["l_aename"].describe().reset_index()
index l_aename
0 count 12674.000000
1 mean 14.680054
2 std 9.101988
3 min 1.000000
4 25% 9.000000
5 50% 13.000000
6 75% 18.000000
7 max 200.000000
Hide code cell content
# l_aenameで降順ソートし、特定の列のみ抽出して冒頭5レコードを表示
df_ae_crt.sort_values("l_aename", ascending=False)[
    ["acname", "aename", "l_aename"]
].head()
acname aename l_aename
2170 School Rumble [突然の「さよなら」…迷い 込んだラビリンス…あなたはだれ? …教えて。「すれちがい」「片想... 200.0
4762 銀魂 仕事のグチは家でこぼさず外でこぼせ!って言うからちょっとこぼさせてもらうけどね「侍の国」僕ら... 183.0
3926 【俗・】さよなら絶望先生 絶望ファイト絶望の大逆転戦法!(3/2)一人より女夫の方がええいうことでっしゃろ(3/2)絶... 130.0
6434 バクマン。[第3期] デラマン。[第1回](9/23) メモリーズ #1 “最高と秋人”(9/23) メモリーズ ... 129.0
6433 バクマン。[第3期] デラマン。[第1回](9/23) メモリーズ #1 “最高と秋人”(9/23) メモリーズ ... 129.0
Hide code cell content
# df_ae_crtデータフレームを"acid"と"acname"のカラムでグループ化し、
# 各グループの"l_aename"カラムに対する基本統計を計算してDataFrameに変換
df_tmp = df_ae_crt.groupby(["acid", "acname"])["l_aename"].describe().reset_index()

# 得られた統計要約df_tmpを"mean"カラム(平均値)に基づいて降順にソートし上位5行を表示
df_tmp.sort_values("mean", ascending=False).head()
acid acname count mean std min 25% 50% 75% max
106 C13492 もっと ToLOVEる 24.0 71.000000 3.867366 66.0 67.75 71.0 74.0 79.0
73 C12181 生徒会 役員共 13.0 62.076923 17.303475 14.0 58.00 70.0 72.0 76.0
143 C14951 生徒会 役員共* 14.0 48.928571 10.608156 29.0 43.75 48.0 54.0 69.0
57 C11615 【俗・】さよなら絶望先生 13.0 45.230769 26.739963 24.0 34.00 39.0 41.0 130.0
118 C13840 侵略!? イカ娘 The Invader comes from the bottom of ... 12.0 43.083333 2.998737 37.0 41.75 43.5 45.0 48.0
Hide code cell content
# df_ae_crtから"acname"が"もっと ToLOVEる"に一致する行をフィルタリング
# その結果から"aename"カラムを選択し、最初の要素を取得
df_ae_crt[df_ae_crt["acname"] == "もっと ToLOVEる"]["aename"].iloc[0]
'もっとトラブル01\u3000もう一度ここから(10/6)\u3000もっとトラブル02\u3000お風呂場戦争(10/6)\u3000もっとトラブル03\u3000チクタク チクタク 恋の音▽*'

acidacname列の深掘り#

Hide code cell content
# mcnameごとのユニークなacid数を集計し、n_ac列に結果を格納して表示
df_ae_crt.groupby("mcname")["acid"].nunique().reset_index(name="n_ac")
mcname n_ac
0 週刊少年サンデー 56
1 週刊少年ジャンプ 104
2 週刊少年チャンピオン 20
3 週刊少年マガジン 58
Hide code cell content
# 'mcname'(マンガ雑誌名)と'acid'(アニメ作品ID)でグループ化し、
# 各グループ内でユニークな'atsname'(放送枠名)の数を集計
df_tmp = (
    df_ae_crt.groupby(["mcname", "acid"])["atsname"].nunique().reset_index(name="n_ats")
)

# 上記で集計したデータを'mcname'(マンガ雑誌名)でさらにグループ化し、
# 各マンガ雑誌名ごとに放送枠の数('n_ats')の要約統計量を計算
df_tmp.groupby("mcname")["n_ats"].describe().reset_index()
mcname count mean std min 25% 50% 75% max
0 週刊少年サンデー 56.0 46.071429 97.280823 1.0 13.0 26.0 46.25 727.0
1 週刊少年ジャンプ 104.0 59.500000 98.698718 1.0 13.0 26.0 61.00 759.0
2 週刊少年チャンピオン 20.0 20.850000 12.832012 1.0 12.0 20.5 25.25 60.0
3 週刊少年マガジン 58.0 31.689655 31.557915 1.0 13.0 25.0 38.00 175.0

asid列の深堀り#

Hide code cell content
# mcnameごとのユニークなasid数と(参考情報として)acid数を集計して表示
df_ae_crt.groupby("mcname").agg(
    n_as=("asid", "nunique"), n_ac=("acid", "nunique")
).reset_index()
mcname n_as n_ac
0 週刊少年サンデー 35 56
1 週刊少年ジャンプ 63 104
2 週刊少年チャンピオン 12 20
3 週刊少年マガジン 42 58
Hide code cell content
# 'mcname'(マンガ雑誌名)と'asid'(アニメシリーズID)でグループ化し、
# 各グループ内でユニークな'atsname'(放送枠名)の数を集計
df_tmp = (
    df_ae_crt.groupby(["mcname", "asid"])["atsname"].nunique().reset_index(name="n_ats")
)

# 上記で集計したデータを'mcname'(マンガ雑誌名)でさらにグループ化し、
# 各マンガ雑誌名ごとに放送枠の数('n_ats')の要約統計量を計算
df_tmp.groupby("mcname")["n_ats"].describe().reset_index()
mcname count mean std min 25% 50% 75% max
0 週刊少年サンデー 35.0 73.714286 125.158857 12.0 26.50 50.0 56.5 752.0
1 週刊少年ジャンプ 63.0 98.222222 134.832446 9.0 31.00 53.0 98.5 759.0
2 週刊少年チャンピオン 12.0 34.750000 26.385688 12.0 13.00 25.0 49.5 87.0
3 週刊少年マガジン 42.0 43.761905 51.435875 11.0 13.75 26.0 50.5 277.0

n_ae列の深掘り#

Hide code cell content
# 'date'列でデータを昇順にソートし、新しいインデックスを付与
# これにより、日付が古い順にデータが並び替えられる
df_ae_crt = df_ae_crt.sort_values("date", ignore_index=True)

# 'acid'列で重複するレコードを削除し、新しいインデックスを付与
# 各アニメ作品名('acid')に対して、最初に出現するレコードだけが保持される
df_ac_crt = df_ae_crt.drop_duplicates(subset=["acid"], ignore_index=True)
Hide code cell content
# n_ae列の要約統計量を算出
# reset_index()メソッドで、結果のインデックスをリセットして、それを新しいデータフレームとして取得
df_ac_crt["n_ae"].describe().reset_index()
index n_ae
0 count 238.000000
1 mean 47.928571
2 std 85.058723
3 min 1.000000
4 25% 13.000000
5 50% 26.000000
6 75% 50.000000
7 max 783.000000
Hide code cell content
# n_ae列の要約統計量を算出
df_ac_crt.groupby("mcname")["n_ae"].describe()
count mean std min 25% 50% 75% max
mcname
週刊少年サンデー 56.0 47.410714 97.549573 1.0 20.50 26.0 50.00 729.0
週刊少年ジャンプ 104.0 61.471154 102.619096 1.0 13.00 26.0 61.25 783.0
週刊少年チャンピオン 20.0 21.650000 13.152046 1.0 12.75 23.5 25.25 63.0
週刊少年マガジン 58.0 33.206897 31.871319 2.0 13.00 26.0 44.25 175.0

first_datelast_date列の深掘り#

Hide code cell content
# df_ae_crtデータフレームから重複する行を削除し、指定された列だけを選択して新しいデータフレームdf_ac_datesを作成
# 'acid'列を基準に重複を排除し、ignore_index=Trueで新しいインデックスを割り当て
df_ac_dates = df_ae_crt.drop_duplicates(subset=["acid"], ignore_index=True)[
    ["mcname", "acname", "first_date", "last_date", "n_ae"]
]

# 'first_date'列と'last_date'列のデータを日付型に変換
df_ac_dates["first_date"] = pd.to_datetime(df_ac_dates["first_date"])
df_ac_dates["last_date"] = pd.to_datetime(df_ac_dates["last_date"])

# 'last_date'と'first_date'の差(期間)を計算して新しい列'duration'に保存
df_ac_dates["duration"] = df_ac_dates["last_date"] - df_ac_dates["first_date"]
Hide code cell content
# first_dateとlast_dateの要約統計量を表示
df_ac_dates[["first_date", "last_date"]].describe()
first_date last_date
count 238 238
mean 2007-04-28 10:11:05.546218496 2008-04-15 19:09:34.789915904
min 1990-01-14 00:00:00 1990-12-24 00:00:00
25% 2002-05-18 00:00:00 2004-03-21 12:00:00
50% 2007-10-01 12:00:00 2008-08-29 00:00:00
75% 2013-06-16 06:00:00 2014-03-29 18:00:00
max 2017-07-05 00:00:00 2017-09-30 00:00:00
Hide code cell content
# duration列の要約統計量を取得し、reset_index()メソッドでDataFrame化して表示
df_ac_dates["duration"].describe().reset_index()
index duration
0 count 238
1 mean 353 days 08:58:29.243697480
2 std 683 days 01:53:27.886971808
3 min 0 days 00:00:00
4 25% 84 days 00:00:00
5 50% 175 days 00:00:00
6 75% 356 days 18:00:00
7 max 6276 days 00:00:00
Hide code cell content
# 'duration'列を'n_ae'列で割って、各レコードについての平均間隔('interval')を算出
df_ac_dates["interval"] = df_ac_dates["duration"] / df_ac_dates["n_ae"]

# 'interval'列に対して要約統計量を取得し、reset_index()メソッドでDataFrame化して表示
df_ac_dates["interval"].describe().reset_index()
index interval
0 count 238
1 mean 7 days 01:29:51.880598083
2 std 4 days 00:30:03.634059959
3 min 0 days 00:00:00
4 25% 6 days 11:04:36.923076923
5 50% 6 days 19:41:32.307692307
6 75% 7 days 05:34:17.142857142
7 max 54 days 16:00:00
Hide code cell content
# intervalで昇順にソートし、上位5作品を表示
df_ac_dates.sort_values("interval").head()
mcname acname first_date last_date n_ae duration interval
153 週刊少年チャンピオン みつ どもえ 特別編 2011-03-07 2011-03-07 1 0 days 0 days
94 週刊少年ジャンプ こちら葛飾区 亀有公園前 派出所 [スペシャル] 走れ! 両津式チンチン電車 ~思い出の大次郎号~ 2006-04-02 2006-04-02 1 0 days 0 days
142 週刊少年サンデー まじっく快斗 KID THE PHANTOM THIEF 第1話 「蘇る怪盗」 2010-04-17 2010-04-17 1 0 days 0 days
103 週刊少年ジャンプ こちら葛飾区 亀有公園前 派出所 [スペシャル] 両津の 浅草リニューアル 大作戦!! ~あ... 2006-09-24 2006-09-24 1 0 days 0 days
215 週刊少年マガジン 金田一 少年の 事件簿R Special 明智警部の事件簿 2015-12-26 2015-12-26 2 0 days 0 days
Hide code cell content
# intervalで降順にソートし、上位5作品を表示
df_ac_dates.sort_values("interval", ascending=False).head()
mcname acname first_date last_date n_ae duration interval
93 週刊少年ジャンプ 聖闘士星矢冥王 ハーデス冥界編[後章] 2006-01-21 2006-12-15 6 328 days 54 days 16:00:00
0 週刊少年ジャンプ シティーハンター3 1990-01-14 1990-12-24 13 344 days 26 days 11:04:36.923076923
124 週刊少年ジャンプ 聖闘士星矢冥王 ハーデスエリシオン編 2008-03-07 2008-08-01 6 147 days 24 days 12:00:00
169 週刊少年ジャンプ 銀魂'[延長戦] 2012-10-04 2013-03-28 13 175 days 13 days 11:04:36.923076923
90 週刊少年サンデー メジャー[第2期] 2005-12-10 2007-01-03 30 389 days 12 days 23:12:00
Hide code cell content
# acnameがシティーハンター3と一致するレコードを抽出し、一部の列を表示
df_ae_crt[df_ae_crt["acname"] == "シティーハンター3"][["aeno", "aename", "date"]]
aeno aename date
0 12 (126) グッバイCITY さよならの 贈りもの (前 編) 1990-01-14
1 13 (127) グッバイCITY さよならの 贈りもの (後 編) 1990-01-21
9 1 (115) 脱モッコリ宣言! XYZは世界を救う 1990-10-15
12 2 (116) 天下の恋愛現行犯! 美人弁護士をくどく法 1990-10-22
15 3 (117) 香もプッツン! 僚*と令嬢代打結婚物語"" 1990-10-29
17 4 (118) 危ない探偵ごっこ! お嬢さんにパイソンを (前 編) 1990-11-05
20 5 (119) 危ない探偵ごっこ! お嬢さんにパイソンを (後 編) 1990-11-12
23 6 (120) がんこな海坊主! ジェラシー子猫物語 1990-11-19
26 7 (121) 恋はダイビング! 美女が水着に着がえたら 1990-11-26
29 8 (122) 僚*って何者? 女子大生もスリルにメロメロ 1990-12-03
32 9 (123) 雨のち晴の恋予報! 美人キャスタに愛の傘 1990-12-10
35 10 (124) クリスマスに ウェディング ドレスを… (前 編) 1990-12-17
38 11 (125) クリスマスに ウェディング ドレスを… (後 編) 1990-12-24

ccidccname列の深掘り#

Hide code cell content
# df_ae_crtから重複する'acid'(アニメ作品名)を削除し、
# 'ccname'と'acname'の列だけを選択して新しいデータフレームを作成
df_ccname_acname = df_ae_crt.drop_duplicates(subset=["acid"])[
    ["mcname", "ccname", "acname"]
].reset_index(drop=True)

# 新しいデータフレームに対して、'ccname'と'acname'の文字列間の類似度を計算し、
# その結果を'similarity'列として追加
# ここで、1は完全一致、0は全く異なる場合を意味する
df_ccname_acname["similarity"] = df_ccname_acname.apply(
    lambda row: difflib.SequenceMatcher(None, row["ccname"], row["acname"]).ratio(),
    axis=1,
)
Hide code cell content
# 類似度が低いアニメ作品を10レコード表示
df_ccname_acname.sort_values(["similarity", "ccname"]).head(10)
mcname ccname acname similarity
194 週刊少年ジャンプ DRAGON BALL ドラゴンボール改[第2期] 0.000000
80 週刊少年サンデー MAJOR メジャー 0.000000
90 週刊少年サンデー MAJOR メジャー[第2期] 0.000000
110 週刊少年サンデー MAJOR メジャー[第3期] 0.000000
121 週刊少年サンデー MAJOR メジャー[第4期] 0.000000
130 週刊少年サンデー MAJOR メジャー[第5期] 0.000000
141 週刊少年サンデー MAJOR メジャー[第6期] 0.000000
75 週刊少年マガジン スクールランブル School Rumble 0.000000
95 週刊少年マガジン スクールランブル School Rumble 二学期 0.000000
34 週刊少年ジャンプ HUNTER×HUNTER ハンター×ハンター 0.090909
Hide code cell content
# df_ccname_acnameデータフレームの'similarity'列を選択し、要約統計量を取得
# reset_index()メソッドで、結果のインデックスをリセットして、それを新しいデータフレームとして取得
df_ccname_acname["similarity"].describe().reset_index()
index similarity
0 count 238.000000
1 mean 0.723755
2 std 0.287821
3 min 0.000000
4 25% 0.533333
5 50% 0.800000
6 75% 1.000000
7 max 1.000000
Hide code cell content
# mcnameごとにsimilarity列の要約統計量を算出
df_ccname_acname.groupby("mcname")["similarity"].describe()
count mean std min 25% 50% 75% max
mcname
週刊少年サンデー 56.0 0.659172 0.349151 0.0 0.369048 0.732143 1.0 1.0
週刊少年ジャンプ 104.0 0.768607 0.234002 0.0 0.608037 0.800000 1.0 1.0
週刊少年チャンピオン 20.0 0.750598 0.273587 0.2 0.571429 0.850000 1.0 1.0
週刊少年マガジン 58.0 0.696430 0.306820 0.0 0.463801 0.800000 1.0 1.0
Hide code cell content
# mcnameが週刊少年サンデーに一致するレコードに対して、similarityを基準に昇順ソート
# 上位10作品を表示
df_ccname_acname[df_ccname_acname["mcname"] == "週刊少年サンデー"].sort_values(
    "similarity"
).head(10)
mcname ccname acname similarity
121 週刊少年サンデー MAJOR メジャー[第4期] 0.000000
80 週刊少年サンデー MAJOR メジャー 0.000000
110 週刊少年サンデー MAJOR メジャー[第3期] 0.000000
130 週刊少年サンデー MAJOR メジャー[第5期] 0.000000
141 週刊少年サンデー MAJOR メジャー[第6期] 0.000000
90 週刊少年サンデー MAJOR メジャー[第2期] 0.000000
9 週刊少年サンデー ゴーストスイーパー美神 極楽大作戦!! GS美神 0.173913
170 週刊少年サンデー ハヤテのごとく! ハヤテのごとく! Hayate the combat buttler CAN'T TAKE ... 0.231884
206 週刊少年サンデー 電波教師 電波教師 HE IS AN ULTIMATE TEACHER 0.235294
54 週刊少年サンデー ARMS PROJECT ARMS The 2nd Chapter 0.250000

mcname列の深堀り#

Hide code cell content
# df_ae_crtデータフレームを'mcname'列に基づいてグループ化し、
# [[...]].nunique()で、指定された列について各グループ内のユニークな値の数を計算
df_ae_crt.groupby("mcname")[["aeid", "acid", "asid", "ccid", "crtid"]].nunique()
aeid acid asid ccid crtid
mcname
週刊少年サンデー 2655 56 35 37 34
週刊少年ジャンプ 6393 104 63 64 64
週刊少年チャンピオン 433 20 12 13 14
週刊少年マガジン 1926 58 42 43 43

crtidcrtname列の深掘り#

Hide code cell content
# groupby(["crtid", "crtname"])で、これらの列の組み合わせごとにデータをグループ化
# .nunique()で、指定された列について各グループ内のユニークな値の数を計算
# .reset_index()で、結果のインデックスをリセットして、それを新しいデータフレームとして取得
df_crt_nunique = (
    df_ae_crt.groupby(["crtid", "crtname"])[["asid", "acid", "aeid", "date"]]
    .nunique()
    .reset_index()
)

# 計算したユニークな値の数について、'asid', 'acid', 'aeid', 'date'の各列の統計的な要約を取得
df_crt_nunique[["asid", "acid", "aeid", "date"]].describe()
asid acid aeid date
count 154.000000 154.000000 154.000000 154.000000
mean 1.168831 1.792208 82.467532 79.610390
std 0.454537 1.255968 121.545665 116.732436
min 1.000000 1.000000 11.000000 7.000000
25% 1.000000 1.000000 26.000000 26.000000
50% 1.000000 1.000000 49.000000 47.500000
75% 1.000000 2.000000 76.000000 74.750000
max 4.000000 8.000000 806.000000 782.000000
Hide code cell content
# アニメ作品数で降順ソートし、上位5名を表示
df_crt_nunique.sort_values("acid", ascending=False).head()
crtid crtname asid acid aeid date
117 CCRT02724 秋本治 1 8 209 207
59 CCRT01512 小畑健 4 6 220 218
100 CCRT02446 満田拓也 1 6 160 159
4 CCRT00188 さとうふみや 2 6 258 244
47 CCRT01321 天樹征丸 2 6 258 244
Hide code cell content
# crtnameが秋本治と一致するレコードのうち、acnameごとに先頭の行を抽出し、特定の列のみ表示
df_ae_crt[df_ae_crt["crtname"] == "秋本治"].groupby("acname")[
    ["n_ae", "first_date", "ccname"]
].first()
n_ae first_date ccname
acname
こちら葛*飾区 亀有公園前 派出所[2016年スペシャル] 1 2016-09-18 こちら葛飾区亀有公園前派出所
こちら葛*飾区亀有公園前派出所[10月SP] 2 2008-10-26 こちら葛飾区亀有公園前派出所
こちら葛*飾区亀有公園前派出所[4月SP] 2 2008-04-06 こちら葛飾区亀有公園前派出所
こちら葛飾区 亀有公園前 派出所 [スペシャル] 両津の 浅草リニューアル 大作戦!! ~あぁ 思い出の花やしき~ 1 2006-09-24 こちら葛飾区亀有公園前派出所
こちら葛飾区 亀有公園前 派出所 [スペシャル] 走れ! 両津式チンチン電車 ~思い出の大次郎号~ 1 2006-04-02 こちら葛飾区亀有公園前派出所
こちら葛飾区亀有公園前派出所 198 1999-12-05 こちら葛飾区亀有公園前派出所
こちら葛飾区亀有公園前派出所 シートン探検隊!隅田川の誓い~思い出の白い鯨を探せ!~ 2 2007-08-05 こちら葛飾区亀有公園前派出所
こちら葛飾区亀有公園前派出所 両さんの寿司食いねぇ!~頂上マグロ対決!!~ 2 2007-09-30 こちら葛飾区亀有公園前派出所
Hide code cell content
# アニメシリーズ数で降順ソートし、上位5名を表示
df_crt_nunique.sort_values("asid", ascending=False).head()
crtid crtname asid acid aeid date
59 CCRT01512 小畑健 4 6 220 218
102 CCRT02471 瀬尾公治 3 3 50 50
29 CCRT00957 冨樫義博 3 4 336 336
84 CCRT02215 椎名高志 2 2 97 97
139 CCRT03016 赤松健 2 2 50 50
Hide code cell content
# crtnameが小畑健と一致するレコードのうち、asidごとに先頭の行を抽出し、特定の列のみ表示
df_ae_crt[df_ae_crt["crtname"] == "小畑健"].groupby("asid")[
    ["acname", "n_ae", "first_date", "ccname"]
].first()
acname n_ae first_date ccname
asid
C2285 人形[からくり]草紙 あやつり 左近 26 1999-08-16 人形草子あやつり左近
C2531 ヒカルの碁 76 2001-10-10 ヒカルの碁
C3898 DEATH NOTE 39 2006-10-04 DEATH NOTE
C4435 バクマン。[第1期] 27 2010-10-02 バクマン。
Hide code cell content
# crtnameが高橋留美子と一致するレコードのうち、asidごとに先頭の行を抽出し、特定の列のみ表示
df_ae_crt[df_ae_crt["crtname"] == "高橋留美子"].groupby("asid")[
    ["acname", "n_ae", "first_date", "ccname"]
].first()
acname n_ae first_date ccname
asid
C2413 犬夜叉 171 2000-10-16 犬夜叉
C5983 境界の RINNE 26 2015-03-22 境界のRINNE
Hide code cell content
# grepコマンドで、うる星やつらを含む文字列をae_dropped.csvから抽出
!grep うる星やつら ../../../data/an/interim/ae_dropped.csv
M22149,,,,C7956,うる星やつら,C5678
Hide code cell content
# grepコマンドで、めぞん一刻を含む文字列をae_dropped.csvから抽出
!grep めぞん一刻 ../../../data/an/interim/ae_dropped.csv
M22488,,,,C8305,めぞん一刻,C6857
Hide code cell content
# grepコマンドで、らんま1/2を含む文字列をae_dropped.csvから抽出
!grep らんま1/2 ../../../data/an/interim/ae_dropped.csv
M23689,,,,C8055,らんま1/2,C7122
M23753,"・第1話/激突! 出前格闘レース(1989/10/20),・第2話/やっぱり猫が嫌い?(1989/11/03),・第3話/私が女傑族のおばば!(1989/11/10),・第4話/出た! 必殺天津甘栗拳!!(1989/11/17),・第5話/白鳥拳の男ムース登場!(1989/11/24),・第6話/爆走! 雪だるま運びレース(1989/12/01),・第7話/さらわれたPちゃん!(1989/12/08),・第8話/危機一髪! 死霊の盆踊り(1989/12/15)<B",,,C8595,らんま1/2 熱闘編,C7122

mix_ce_ac.csvの基礎分析#

Hide code cell content
# pandasのread_csv関数でCSVファイルの読み込み
df_ce_ac = pd.read_csv(DIR_IN / FN_CE_AC)

全体像の把握#

Hide code cell content
# df_ce_acデータフレームの先頭5行を表示
# headメソッドはデータの概観を確認するのに便利
df_ce_ac.head().T
0 1 2 3 4
ceid CE00000 CE00026 CE00062 CE00086 CE00112
cename 第238話/この世代 第237話/トーナメント 第236話/絆 第235話/指先から… 第234話/何にも出来ないワケじゃない
ccid C90829 C90829 C90829 C90829 C90829
miid M535428 M535429 M535430 M535431 M535432
page_start 10.0 125.0 223.0 183.0 221.0
page_end 31.0 144.0 242.0 204.0 240.0
pages 22.0 20.0 20.0 22.0 20.0
page_start_position 0.021368 0.23855 0.478541 0.405765 0.472222
two_colored False False False False False
four_colored True False False False False
date 2011-05-25 2011-05-18 2011-05-04 2011-04-27 2011-04-20
ccname ダイヤのA ダイヤのA ダイヤのA ダイヤのA ダイヤのA
n_ce 425 425 425 425 425
n_2c 0 0 0 0 0
n_4c 39 39 39 39 39
first_date_cc 2006-05-31 2006-05-31 2006-05-31 2006-05-31 2006-05-31
last_date_cc 2016-01-08 2016-01-08 2016-01-08 2016-01-08 2016-01-08
mcid C119033 C119033 C119033 C119033 C119033
mcname 週刊少年マガジン 週刊少年マガジン 週刊少年マガジン 週刊少年マガジン 週刊少年マガジン
acid C14866 C14866 C14866 C14866 C14866
acname ダイヤのA[エース] ダイヤのA[エース] ダイヤのA[エース] ダイヤのA[エース] ダイヤのA[エース]
asid C5641 C5641 C5641 C5641 C5641
n_ae 75.0 75.0 75.0 75.0 75.0
first_date_ac 2013-10-06 2013-10-06 2013-10-06 2013-10-06 2013-10-06
last_date_ac 2015-03-29 2015-03-29 2015-03-29 2015-03-29 2015-03-29
Hide code cell content
# df_ce_acデータフレームの形状(行数・列数)を取得
# shape属性を使用すると、(行数, 列数)の形で結果が返される
df_ce_ac.shape
(181681, 25)
Hide code cell content
# df_ce_acデータフレーム内の欠損値(NaN)の情報を集計
# isna()メソッドを使用して欠損値の場所をTrueとして特定
# その後、agg()メソッドを使用して、各列における欠損値の合計と平均を計算し転置して表示
df_ce_ac.isna().agg([sum, "mean"]).T
sum mean
ceid 0.0 0.000000
cename 27536.0 0.151562
ccid 0.0 0.000000
miid 0.0 0.000000
page_start 0.0 0.000000
page_end 0.0 0.000000
pages 0.0 0.000000
page_start_position 0.0 0.000000
two_colored 0.0 0.000000
four_colored 0.0 0.000000
date 1614.0 0.008884
ccname 0.0 0.000000
n_ce 0.0 0.000000
n_2c 0.0 0.000000
n_4c 0.0 0.000000
first_date_cc 0.0 0.000000
last_date_cc 0.0 0.000000
mcid 0.0 0.000000
mcname 0.0 0.000000
acid 138157.0 0.760437
acname 138157.0 0.760437
asid 138157.0 0.760437
n_ae 138157.0 0.760437
first_date_ac 138157.0 0.760437
last_date_ac 138157.0 0.760437
Hide code cell content
# df_ce_acデータフレームの記述統計情報を取得
# describe()メソッドを使用して、各列の中央値、平均、標準偏差などの基本的な統計量を転置表示
df_ce_ac.describe().T
count mean std min 25% 50% 75% max
page_start 181681.0 209.882924 123.920451 1.000000 107.000000 203.000000 305.000000 581.0
page_end 181681.0 227.382651 122.137365 1.000000 125.000000 221.000000 322.000000 600.0
pages 181681.0 18.499728 7.712246 1.000000 17.000000 19.000000 20.000000 487.0
page_start_position 181681.0 0.514276 0.283281 0.002045 0.273529 0.519737 0.759524 1.0
n_ce 181681.0 218.286887 265.554237 1.000000 55.000000 152.000000 285.000000 1968.0
n_2c 181681.0 6.906451 15.956542 0.000000 0.000000 0.000000 6.000000 161.0
n_4c 181681.0 16.014608 26.655401 0.000000 1.000000 6.000000 19.000000 200.0
n_ae 43524.0 98.339008 156.534637 1.000000 25.000000 46.000000 97.000000 783.0
Hide code cell content
# df_ce_acデータフレームの各列に対してユニークな値の数をカウント
# nunique()メソッドを使用して、各列のユニークな値の数を計算
# その後、結果を新しいデータフレームとして整形し、列名を"nunique"とする
df_ce_ac.nunique().reset_index(name="nunique")
index nunique
0 ceid 181681
1 cename 151204
2 ccid 6953
3 miid 9822
4 page_start 550
5 page_end 568
6 pages 123
7 page_start_position 45726
8 two_colored 2
9 four_colored 2
10 date 6380
11 ccname 6845
12 n_ce 340
13 n_2c 52
14 n_4c 65
15 first_date_cc 4376
16 last_date_cc 4160
17 mcid 4
18 mcname 4
19 acid 157
20 acname 157
21 asid 152
22 n_ae 63
23 first_date_ac 147
24 last_date_ac 151

date列の深堀り#

Hide code cell content
# year列に年情報を追加
df_ce_ac["year"] = pd.to_datetime(df_ce_ac["date"]).dt.year
Hide code cell content
# 'acname'列の欠損値(NaN)の有無に基づいて、新しい列'is_animated'を作成
# 'acname'列に値があればTrue(アニメーションあり)、欠損値ならFalse(アニメーションなし)
df_ce_ac["is_animated"] = ~df_ce_ac["acname"].isna()

# date列から年情報を抜き出し、year列として格納
df_ce_ac["year"] = pd.to_datetime(df_ce_ac["date"]).dt.year
# year列を5年ごとに集計するためのyears列を追加
unit_years = 5
df_ce_ac["years"] = df_ce_ac["year"] // unit_years * unit_years
# yearsごとにis_animatedの平均値を算出
df_ce_ac.groupby("years")["is_animated"].mean().reset_index()
years is_animated
0 1970.0 0.053436
1 1975.0 0.070777
2 1980.0 0.073442
3 1985.0 0.099111
4 1990.0 0.189754
5 1995.0 0.280905
6 2000.0 0.340570
7 2005.0 0.362271
8 2010.0 0.404778
9 2015.0 0.323192

ceidcename列の深掘り#

Hide code cell content
# 'is_animated'列(アニメーションがあるかないか)に基づいてデータをグループ化し、
# 'ceid'のユニークな値の数をそれぞれのグループで計算
# .reset_index()で、結果のインデックスをリセットして、それを新しいデータフレームとして取得
df_ce_ac.groupby("is_animated")["ceid"].nunique().reset_index()
is_animated ceid
0 False 138157
1 True 43524
Hide code cell content
# df_ce_acデータフレームを'mcname'に基づいてグループ化し、'is_animated'列に対して集約関数を適用
# .reset_index()で、結果のインデックスをリセットして、それを新しいデータフレームとして取得
df_ce_ac.groupby("mcname")["is_animated"].agg(["count", "sum", "mean"]).reset_index()
mcname count sum mean
0 週刊少年サンデー 46491 10240 0.220258
1 週刊少年ジャンプ 43371 18167 0.418874
2 週刊少年チャンピオン 45443 3224 0.070946
3 週刊少年マガジン 46376 11893 0.256447

ccidccname列の深掘り#

Hide code cell content
# 'is_animated'列(アニメーションがあるかないか)に基づいてデータをグループ化し、
# 'ccid'のユニークな値の数をそれぞれのグループで計算
# .reset_index()で、結果のインデックスをリセットして、それを新しいデータフレームとして取得
df_ce_ac.groupby("is_animated")["ccid"].nunique().reset_index()
is_animated ccid
0 False 6796
1 True 157
Hide code cell content
# df_ce_acデータフレームから'ccid'列を基準に重複を削除し
# 新しいインデックスを割り当てて新しいデータフレームdf_tmpを作成
df_tmp = df_ce_ac.drop_duplicates(subset=["ccid"], ignore_index=True)

# df_tmpデータフレームを'mcname'に基づいてグループ化し、
# 'is_animated'列に対して複数の集約関数(カウント、合計、平均)を適用
# .reset_index()で、結果のインデックスをリセットして、それをさらに扱いやすい形に整形
df_tmp.groupby("mcname")["is_animated"].agg(["count", "sum", "mean"]).reset_index()
mcname count sum mean
0 週刊少年サンデー 1496 37 0.024733
1 週刊少年ジャンプ 2129 64 0.030061
2 週刊少年チャンピオン 1736 13 0.007488
3 週刊少年マガジン 1592 43 0.027010

miid列の深掘り#

Hide code cell content
# df_ce_acデータフレームから'miid'と'ccname'の組み合わせで重複を削除し
# 新しいインデックスを割り当てて新しいデータフレームdf_tmpを作成
# (特別企画等で同一マンガ作品が複数回掲載されているパターンがあるため)
df_tmp = df_ce_ac.drop_duplicates(subset=["miid", "ccname"], ignore_index=True)

# df_tmpデータフレームを'mcname'と'miid'に基づいてグループ化し
# 'is_animated'列に対して合計と平均を計算
# .reset_index()で、結果のインデックスをリセット
df_mi_animated = (
    df_tmp.groupby(["mcname", "miid"])["is_animated"]
    .agg(["count", "sum", "mean"])
    .reset_index()
)

# 内容を表示
df_mi_animated.tail()
mcname miid count sum mean
10107 週刊少年マガジン M702008 22 6 0.272727
10108 週刊少年マガジン M702009 24 7 0.291667
10109 週刊少年マガジン M702010 23 5 0.217391
10110 週刊少年マガジン M702011 27 9 0.333333
10111 週刊少年マガジン M702012 24 7 0.291667
Hide code cell content
# sum、mean列について要約統計量を算出
df_mi_animated[["sum", "mean"]].describe()
sum mean
count 10112.000000 10112.000000
mean 4.255538 0.212150
std 4.427726 0.211994
min 0.000000 0.000000
25% 0.000000 0.000000
50% 2.000000 0.130435
75% 8.000000 0.375000
max 16.000000 1.000000
Hide code cell content
# アニメ化作品数の順に降順ソートし、上位5巻号を表示
df_mi_animated.sort_values(["sum", "mean", "miid"], ascending=False).head()
mcname miid count sum mean
4756 週刊少年ジャンプ M616464 21 16 0.761905
2725 週刊少年ジャンプ M542873 21 16 0.761905
2724 週刊少年ジャンプ M542872 21 16 0.761905
2723 週刊少年ジャンプ M542871 21 16 0.761905
2722 週刊少年ジャンプ M542870 21 16 0.761905
Hide code cell content
# miidがM616464と一致し、かつアニメ化実績があるマンガ作品名一覧を取得
df_ce_ac[(df_ce_ac["miid"] == "M616464") & df_ce_ac["is_animated"]]["ccname"].unique()
array(['こちら葛飾区亀有公園前派出所', 'ONE PIECE', 'トリコ', 'NARUTO-ナルト-', 'SKET DANCE',
       '銀魂', 'べるぜバブ', 'めだかボックス', 'BLEACH', '黒子のバスケ', 'ハイキュー!!', 'ニセコイ',
       '斉木楠雄のΨ難', '暗殺教室', '食戟のソーマ', 'ワールドトリガー'], dtype=object)

page_startpage_endpagespage_start_position列の深掘り#

Hide code cell content
# is_animated別に各指標の平均値を算出
df_ce_ac.groupby("is_animated")[
    ["page_start", "page_end", "pages", "page_start_position"]
].mean()
page_start page_end pages page_start_position
is_animated
False 217.147238 234.696809 18.549570 0.544581
True 186.824017 204.165529 18.341513 0.418081
Hide code cell content
# df_ce_acデータフレームでピボットテーブルを作成
# 'is_animated'をインデックスとして、'mcname'を列とし、
# 'page_start_position'の値に基づく平均値を集約関数として計算
df_ce_ac.pivot_table(
    index="is_animated", columns="mcname", values="page_start_position", aggfunc="mean"
)
mcname 週刊少年サンデー 週刊少年ジャンプ 週刊少年チャンピオン 週刊少年マガジン
is_animated
False 0.539659 0.572595 0.530063 0.547054
True 0.389284 0.433425 0.285667 0.455331

two_coloredfour_colored列の深堀り#

Hide code cell content
# is_animated別に各指標の平均値を算出
df_ce_ac.groupby("is_animated")[["two_colored", "four_colored"]].mean()
two_colored four_colored
is_animated
False 0.044493 0.065281
True 0.019369 0.093787
Hide code cell content
# df_ce_acデータフレームを'ccid'と'ccname'に基づいてグループ化し
# 'two_colored', 'four_colored', 'is_animated', 'n_ce'の各列について平均を計算
# ('is_animated'と'n_ce'に関してはccid内で同じ値を取るため平均をとっても問題ない)
df_cc_colored = (
    df_ce_ac.groupby(["ccid", "ccname"])[
        ["two_colored", "four_colored", "is_animated", "n_ce"]
    ]
    .mean()
    .reset_index()
)

# df_cc_coloredデータフレームを'two_colored'列の値で降順に並び替え、上位5行を表示
df_cc_colored.sort_values("two_colored", ascending=False).head(5)
ccid ccname two_colored four_colored is_animated n_ce
5333 C93922 流血鬼 1.0 0.0 0.0 1.0
3079 C90621 荒野への帰還 1.0 0.0 0.0 1.0
3945 C91841 南野陽子物語 1.0 0.0 0.0 1.0
4633 C92894 コンクリート・ライブ 1.0 0.0 0.0 1.0
2006 C89268 ニートに翔んで 1.0 0.0 0.0 1.0
Hide code cell content
# n_ceの最小値を8として設定
min_nce = 8
# is_animated別に各指標の平均値を算出
df_ce_ac[df_ce_ac["n_ce"] >= min_nce].groupby("is_animated")[
    ["two_colored", "four_colored"]
].mean()
two_colored four_colored
is_animated
False 0.042763 0.060272
True 0.019365 0.093882
Hide code cell content
# 年代別に各指標の平均値を算出して表示
df_ce_ac.groupby("years")[["is_animated", "two_colored", "four_colored"]].mean()
is_animated two_colored four_colored
years
1970.0 0.053436 0.033272 0.094522
1975.0 0.070777 0.126122 0.065824
1980.0 0.073442 0.125217 0.042401
1985.0 0.099111 0.076740 0.042873
1990.0 0.189754 0.035601 0.040300
1995.0 0.280905 0.019133 0.048192
2000.0 0.340570 0.004701 0.067801
2005.0 0.362271 0.000563 0.092917
2010.0 0.404778 0.001373 0.111006
2015.0 0.323192 0.000671 0.120778

n_ce列の深掘り#

Hide code cell content
# df_ce_acデータフレームから'ccid'列を基準に重複を削除し、
# 新しいインデックスを割り当てて新しいデータフレームdf_cc_acを作成
df_cc_ac = df_ce_ac.drop_duplicates(subset=["ccid"], ignore_index=True)

# df_cc_acデータフレームを'is_animated'に基づいてグループ化し、
# 'n_ce'の列についての要約統計量を計算
df_cc_ac.groupby("is_animated")["n_ce"].describe()
count mean std min 25% 50% 75% max
is_animated
False 6796.0 20.142731 50.005947 1.0 1.0 1.0 16.0 635.0
True 157.0 275.012739 225.826516 1.0 161.0 241.0 337.0 1968.0

n_2cn_4c列の深堀り#

Hide code cell content
# df_cc_acデータフレームを'is_animated'に基づいてグループ化し、
# 'n_2c'、'n_4c'の列についての要約統計量を計算して転置表示
# (df_ce_acではなくdf_cc_acであることに注意!)
df_cc_ac.groupby("is_animated")[["n_2c", "n_4c"]].describe().T
is_animated False True
n_2c count 6796.000000 157.000000
mean 0.873896 5.331210
std 4.380116 11.839952
min 0.000000 0.000000
25% 0.000000 0.000000
50% 0.000000 0.000000
75% 0.000000 4.000000
max 161.000000 72.000000
n_4c count 6796.000000 157.000000
mean 1.309005 25.643312
std 4.730921 25.115378
min 0.000000 0.000000
25% 0.000000 9.000000
50% 0.000000 19.000000
75% 1.000000 35.000000
max 200.000000 158.000000
Hide code cell content
# df_cc_acのうち、n_acに関して降順ソートし、特定の列について上位5行を表示
df_cc_ac.sort_values("n_2c", ascending=False)[
    ["mcname", "ccname", "n_ce", "n_2c", "n_4c", "is_animated"]
].head()
mcname ccname n_ce n_2c n_4c is_animated
3232 週刊少年チャンピオン がきデカ 332 161 70 False
3184 週刊少年チャンピオン ドカベン 635 109 200 False
3223 週刊少年チャンピオン らんぽう 457 79 29 False
446 週刊少年マガジン 釣りキチ三平 482 74 17 False
1333 週刊少年ジャンプ キン肉マン 400 72 22 True
Hide code cell content
# grepコマンドで、がきデカを含む文字列をae_dropped.csvから抽出
!grep がきデカ ../../../data/an/interim/ae_dropped.csv
M23737,,,,C8579,がきデカ,C7146

first_date_cclast_date_cc列の深掘り#

Hide code cell content
# 'first_date_cc'列と'last_date_cc'列のデータを日付型に変換
df_cc_ac["first_date_cc"] = pd.to_datetime(df_cc_ac["first_date_cc"])
df_cc_ac["last_date_cc"] = pd.to_datetime(df_cc_ac["last_date_cc"])

# 'is_animated'でデータをグループ化し、'first_date_cc'(最初の日付)と'last_date_cc'(最後の日付)の
# 統計的な要約(count, mean, std, min, 25%, 50%, 75%, max)を計算
# .T(転置)を用いて、結果の表示形式を行と列を入れ替えて、より読みやすく整理
df_cc_ac.groupby("is_animated")[["first_date_cc", "last_date_cc"]].describe().T
is_animated False True
first_date_cc count 6796 157
mean 1993-09-05 08:51:37.822248320 1998-12-17 00:36:41.273885312
min 1970-07-27 00:00:00 1970-08-02 00:00:00
25% 1980-08-24 00:00:00 1993-06-14 00:00:00
50% 1993-03-28 00:00:00 2001-06-06 00:00:00
75% 2006-12-14 00:00:00 2007-08-09 00:00:00
max 2017-07-31 00:00:00 2016-05-23 00:00:00
last_date_cc count 6796 157
mean 1994-04-14 15:13:27.298410880 2007-03-09 00:09:10.318471424
min 1970-07-27 00:00:00 1971-01-17 00:00:00
25% 1981-01-12 00:00:00 2002-05-01 00:00:00
50% 1994-01-01 00:00:00 2009-09-14 00:00:00
75% 2007-11-20 18:00:00 2016-08-31 00:00:00
max 2017-07-31 00:00:00 2017-07-31 00:00:00

mcidmcname列の深掘り#

Hide code cell content
# アニメ化実績のあるマンガ作品に対して、mcnameごとの各列の平均値を算出
df_cc_ac[df_cc_ac["is_animated"]].groupby("mcname")[["n_ce", "n_2c", "n_4c"]].mean()
n_ce n_2c n_4c
mcname
週刊少年サンデー 276.756757 3.621622 20.216216
週刊少年ジャンプ 283.859375 10.265625 32.296875
週刊少年チャンピオン 248.000000 1.692308 34.615385
週刊少年マガジン 268.511628 0.558140 17.697674
Hide code cell content
# 'is_animated'がTrue場合のデータをフィルタリングして、'mcname'でグループ化
# 'n_ce'、'n_2c'、'n_4c'の平均値を計算
df_tmp_animated = (
    df_cc_ac[df_cc_ac["is_animated"]].groupby("mcname")[["n_ce", "n_2c", "n_4c"]].mean()
)

# 全コンテンツ(アニメーションの有無に関わらず)を'mcname'でグループ化し、
# 同じく'n_ce'、'n_2c'、'n_4c'の平均値を計算
df_tmp_all = df_cc_ac.groupby("mcname")[["n_ce", "n_2c", "n_4c"]].mean()

# アニメーションがあるコンテンツの平均値を、全コンテンツの平均値で割る
# これにより、アニメーションがあるコンテンツの特性が全体と比べてどのように異なるかを数値的に把握できる
df_tmp_animated / df_tmp_all
n_ce n_2c n_4c
mcname
週刊少年サンデー 9.024349 3.094201 12.190028
週刊少年ジャンプ 14.023358 9.256889 15.821456
週刊少年チャンピオン 9.474022 2.002622 17.130076
週刊少年マガジン 9.364086 0.742321 10.890877

acidacname列の深掘り#

Hide code cell content
# 'ccname_closest'列を作成し、各行に対して'find_closest_match'関数を適用
# この関数は、現在の行のデータに基づいてdf_cc_acデータフレーム内の最も近いマッチを見つける
# applyメソッドを用いて行ごとに処理を適用する(引数としてdf_cc_acを渡す)
df_cc_ac["ccname_closest"] = df_cc_ac.apply(find_closest_match, axis=1, df=df_cc_ac)

# アニメーションがあるコンテンツ('is_animated'がTrue)のみをフィルタリングし、特定の列を抽出
# reset_index(drop=True)でインデックスをリセットし、新しい連番のインデックスを作成することで、
# 選択したデータを新しいデータフレームdf_tmpとして整理
df_tmp = df_cc_ac[df_cc_ac["is_animated"]][
    ["acname", "ccname", "ccname_closest"]
].reset_index(drop=True)
Hide code cell content
# ccname(原作マンガ作品名の正解)とccname_closest(acnameと最も近いccname)が
# 一致している割合を算出
(df_tmp["ccname"] == df_tmp["ccname_closest"]).mean()
0.8343949044585988
Hide code cell content
# ccnameとccname_closestが一致しない作品リスト
df_tmp[df_tmp["ccname"] != df_tmp["ccname_closest"]]
acname ccname ccname_closest
4 CØDE: BREAKER CODE:BREAKER コード:ブレイカー SWORD BREAKER
7 はじめの 一歩 THE FIGHTING! はじめの一歩 IN THE TRAIN
16 ツバサ・クロニクル 年代記[第1期] ツバサ ~RESERVoir CHRoNiCLE~ バイオハザード アンブレラ・クロニクルズ 崩壊への序曲
17 School Rumble スクールランブル Moon Walker
22 ゲットバッカーズ 奪還屋 Get Backers 奪還屋 ロボットボーイズ
25 RAVE GROOVE ADVENTURE RAVE SPACE ADVENTURE コブラ
28 アソボット戦記 五九 アソボット五九 アソボット戦記五九
36 巨人の星 【特別篇】 猛虎 花形満 ~『巨人の星』全182話より特別編集~ 巨人の星 巨人の星外伝それからの飛雄馬
40 ドクタースランプ Dr.スランプ ドクター・ジュン
54 ハンター×ハンター HUNTER×HUNTER ハングリーハート
71 -仙界伝- 封神 演義 封神演義 異説 封神演義
82 DRAGON BALL KAI DRAGON BALL DRAGON BALL 外伝
87 シティーハンター3 CITY HUNTER シティ・ハンター モンスターハンター
90 COBRA THE ANIMATION SPACE ADVENTURE コブラ 鉄のラインバレル THE ANIMATION
94 侵略! イカ娘 The invader comes from the bottom of t... 侵略!イカ娘 Magazine Heroines on the Beach!!
112 ムシブギョー 蟲奉行 常住戦陣!!ムシブギョー ムシブギョー 蟲奉行
121 まじっく快斗 KID THE PHANTOM THIEF 第1話 「蘇る怪盗」 まじっく快斗 DEATH NOTE
123 MÄR メルヘヴン MÄRCHEN AWAKENS ROMANCE MAR メル AL THE WHITE TRICERATOPS
128 PROJECT ARMS ARMS GOLEM HEARTS
130 メジャー MAJOR 銀輪ジャガー
131 ガンバリスト!駿 ガンバ!!Fly high 俺はガメリスト
133 GS美神 ゴーストスイーパー美神 極楽大作戦!! 荒神
138 人造人間 キカイダー THE ANIMATION 人造人間キカイダー 鉄のラインバレル THE ANIMATION
145 七つの大罪 The Seven Deadly Sins 七つの大罪 MMR The Apocalypse
149 金田一少年の 事件簿R[リターンズ] 金田一少年の事件簿R 金田一少年の事件簿
151 電波教師 HE IS AN ULTIMATE TEACHER 電波教師 ULTIMATE CHASER
Hide code cell content
# ccnameに「アソボット」を含むデータを抽出し、特定の列を表示しつつ、dateで昇順ソート
df_ce_ac[df_ce_ac["ccname"].str.contains("アソボット")][
    ["date", "ccname", "cename", "acname", "first_date_ac"]
].sort_values("date")
date ccname cename acname first_date_ac
18384 2002-01-17 アソボット五九 第1話 大悪党・五九 参上!! アソボット戦記 五九 2002-10-01
18383 2002-01-23 アソボット五九 第2話 ハーモニカを持った少年 アソボット戦記 五九 2002-10-01
18382 2002-01-30 アソボット五九 第3話 ゴータ・マ村長の決意 アソボット戦記 五九 2002-10-01
18381 2002-02-06 アソボット五九 第4話 サルってゆうんじゃねえ! アソボット戦記 五九 2002-10-01
18380 2002-02-13 アソボット五九 第5話 脅威!マリオネットシール アソボット戦記 五九 2002-10-01
18379 2002-02-20 アソボット五九 第6話 ナミダの温度 アソボット戦記 五九 2002-10-01
18378 2002-02-27 アソボット五九 第7話 はるかなる旅路へ アソボット戦記 五九 2002-10-01
18377 2002-03-06 アソボット五九 第8話 美少女盗賊・魅音サマ アソボット戦記 五九 2002-10-01
18376 2002-03-13 アソボット五九 第9話 白い砂漠 アソボット戦記 五九 2002-10-01
18375 2002-03-20 アソボット五九 第10話 強敵・ヤズー現る! アソボット戦記 五九 2002-10-01
18374 2002-03-27 アソボット五九 第11幕 テルミニ村と大蛇神 アソボット戦記 五九 2002-10-01
18373 2002-04-03 アソボット五九 第12話 アップデート大作戦 アソボット戦記 五九 2002-10-01
18372 2002-04-10 アソボット五九 第13話 速攻!敵アジト潜入 アソボット戦記 五九 2002-10-01
18371 2002-04-17 アソボット五九 第14話 悪魔のウイルス アソボット戦記 五九 2002-10-01
18370 2002-04-24 アソボット五九 第15話 再戦!五九vsヤズー アソボット戦記 五九 2002-10-01
18369 2002-05-01 アソボット五九 第16話 決着! アソボット戦記 五九 2002-10-01
18368 2002-05-08 アソボット五九 第17話 蛇神祭 アソボット戦記 五九 2002-10-01
18367 2002-05-15 アソボット五九 第18話 謎、深まる アソボット戦記 五九 2002-10-01
18366 2002-06-05 アソボット五九 特別編 sanzo@rei 第2話 ふたり暮らし アソボット戦記 五九 2002-10-01
18365 2002-06-05 アソボット五九 特別編 sanzo@rei 第1話 プロトタイプ・レイ アソボット戦記 五九 2002-10-01
18364 2002-06-12 アソボット五九 特別編 sanzo@rei 第3話 ワカラナイ アソボット戦記 五九 2002-10-01
18363 2002-06-19 アソボット五九 特別編 sanzo@rei 第4話 「恋」をするということ アソボット戦記 五九 2002-10-01
18362 2002-06-26 アソボット五九 特別編 sanzo@rei 第5話 evolution アソボット戦記 五九 2002-10-01
18361 2002-07-03 アソボット五九 特別編 sanzo@rei 第6話 破局の予感 アソボット戦記 五九 2002-10-01
18360 2002-07-10 アソボット五九 特別編 sanzo@rei 第7話 アダムとイブ アソボット戦記 五九 2002-10-01
18359 2002-07-17 アソボット五九 特別編 sanzo@rei 第8話 最後のナミダ アソボット戦記 五九 2002-10-01
18358 2002-07-24 アソボット五九 特別編 sanzo@rei 第9話 ココロ…終わることなく紡がれて アソボット戦記 五九 2002-10-01
18000 2002-10-09 アソボット戦記五九 前編 五九一家登場! NaN NaN
17999 2002-10-16 アソボット戦記五九 後編 NaN NaN

asid列の深堀り#

Hide code cell content
# asidでグループ化し、mcname、ccname、ccidに関しては先頭のものを抽出
# ceidに関してはユニーク数を集計
df_tmp = (
    df_ce_ac.groupby("asid")
    .agg({"mcname": "first", "ccname": "first", "ccid": "first", "ceid": "nunique"})
    .reset_index()
)
# ceidのユニーク数(つまり合計各話数)の要約統計量を算出
df_tmp["ceid"].describe().reset_index()
index ceid
0 count 152.000000
1 mean 286.342105
2 std 229.496717
3 min 16.000000
4 25% 166.250000
5 50% 244.000000
6 75% 341.250000
7 max 1968.000000
Hide code cell content
# 合計各話数に関して昇順ソートし、上位5行を表示
df_tmp.sort_values("ceid").head(5)
asid mcname ccname ccid ceid
111 C4571 週刊少年ジャンプ レベルE C89851 16
53 C2640 週刊少年マガジン アソボット五九 C90306 27
22 C1994 週刊少年マガジン 中華一番! C90794 30
33 C2285 週刊少年ジャンプ 人形草子あやつり左近 C88332 32
89 C3508 週刊少年ジャンプ 初恋限定。 C89375 32

n_ae列の深掘り#

Hide code cell content
# n_aeに関して降順ソートしたうえで特定の列のみ選択し、上位5行を表示
df_cc_ac.sort_values("n_ae", ascending=False)[
    ["mcname", "ccname", "acname", "n_ae"]
].head()
mcname ccname acname n_ae
1347 週刊少年ジャンプ ONE PIECE ONE PIECE 783.0
4540 週刊少年サンデー 名探偵コナン 名探偵コナン 729.0
1359 週刊少年ジャンプ BLEACH BLEACH 369.0
1349 週刊少年ジャンプ NARUTO-ナルト- NARUTO 221.0
1352 週刊少年ジャンプ 銀魂 銀魂 201.0

first_date_aclast_date_ac列の深掘り#

Hide code cell content
# first_date_acに関して昇順ソートしたうえで特定の列のみ選択し、上位5行を表示
df_cc_ac.sort_values("first_date_ac")[
    ["mcname", "ccname", "acname", "first_date_ac"]
].head(5)
mcname ccname acname first_date_ac
2225 週刊少年ジャンプ CITY HUNTER シティ・ハンター シティーハンター3 1990-01-14
2184 週刊少年ジャンプ まじかる☆タルるートくん まじかる★タルるートくん 1990-09-02
448 週刊少年マガジン 三つ目がとおる 三つ目がとおる 1990-10-18
5407 週刊少年サンデー おれは直角 おれは直角 1991-01-05
1333 週刊少年ジャンプ キン肉マン キン肉マン キン肉星王位争奪編 1991-10-06
Hide code cell content
# acnameにシティーを含む行に対して、acnameの値の数を集計し、reset_indexでDataFrame化
df_ce_ac[df_ce_ac["acname"].str.contains("シティー") > 0][
    "acname"
].value_counts().reset_index()
acname count
0 シティーハンター3 337