4 追加の分析

4.1 主成分分析の利用

ステータスの項目は主要な4項目はほとんどのシリーズで採用されているが, 基本的にシリーズごとに設定は異なる43. 前節では作品ごとの能力値のレンジを補正するために正規化処理をしたが, 項目数は正規化できない. そこで主成分分析(PCA)によって, 全ての項目を数種類の項目に凝縮してみる. 主成分の計算には組み込みの関数 stat::prcomp() を, グラフの描画(バイプロット)には factoextra::fviz_pcabiplot() を使用している. なお, このパッケージもggplot2を利用してグラフを描画している.

get_design_mat_input <- function(df) {
    # デザイン行列作成に必要な列 + title, name_id を取り出す
    df %>% select_if(str_detect(names(.), "name_id") | map_lgl(., ~!is.character(.x))) %>% 
        select(-order, -matches("生年|誕生|没年|登場|顔番号|相性")) %>% 
        drop_na
}
convert_design_mat <- function(df, name = T, center = T, scale = T) {
    # title, name_id 列を除いてデザイン行列に変換する
    # (正規化処理オプションあり)
    model.matrix(~. - 1, select(df, -title, -name_id, -attend_times, -at_first) %>% 
        mutate_if(is.numeric, ~scale(.x, center = center, scale = scale))) %>% 
        magrittr::set_rownames(df$name_id)
}

pca_conveted <- df_all %>% mutate(title = as.integer(title)) %>% group_by(title) %>% 
    group_map(~unnest(.x, cols = data) %>% get_design_mat_input %>% list(title = .$title[1], 
        name = select(., name_id, attend_times), pca = prcomp(convert_design_mat(.), 
            center = F, scale. = F)), keep = T)
PCAは単位もスケールも異なる変数どうしの関係を見る方法であり, スケールを揃えるかどうかで結果も大きく変わってしまう. 多くの場合ではスケールの違いは変数どうしの関係とは直接関係ないため, 特に理由がない限りPCAの入力データは標準化処理したものを使うべきである. prcomp()center, scale.という内部で標準化処理をするためのオプションがあるため, 標準化処理を自分で書くことは必須ではない.

バイプロットは負荷量の多い順に第2主成分までを使った散布図であり, 第1・第2主成分の累積寄与率が高くない場合は, ステータス値による特徴をうまく捉えられない場合もある44 (図4.1).

map_dfr(pca_conveted, ~get_eig(.x$pca) %>% as_tibble(rownames = "d") %>% 
    select(d, variance.percent) %>% mutate(title = .x$title)) %>% mutate(variance.percent = variance.percent/100, 
    d = factor(d, levels = rev(unique(d)))) %>% filter(d %in% paste0("Dim.", 
    1:2)) %>% ggplot(aes(x = title, y = variance.percent, group = d, fill = d)) + 
    geom_bar(stat = "identity", position = "stack") + scale_fill_pander(guide = guide_legend(reverse = TRUE)) + 
    labs(y = "accumurated importance") + scale_y_continuous(labels = scales::percent) + 
    scale_x_continuous(breaks = 1:13) + theme_document
シリーズごとの第2主成分までの累積寄与率

図 4.1: シリーズごとの第2主成分までの累積寄与率

三國志2, 9 についてこの方法で求めた第1・第2主成分でプロットした散布図が図4.2,4.3である.

fviz_pca_biplot(pca_conveted[[2]]$pca) + labs(title = "三國志II", caption = "https://github.com/Gedevan-Aleksizde/Japan.R2019\nデータ出典: http://hima.que.ne.jp/sangokushi/")
三國志2の主成分バイプロット図

図 4.2: 三國志2の主成分バイプロット図

fviz_pca_biplot(pca_conveted[[9]]$pca) + labs(title = "三國志IX", caption = "https://github.com/Gedevan-Aleksizde/Japan.R2019\nデータ出典: http://lee.serio.jp/novel/sangoku/san9busho.html")
三国志9の主成分バイプロット図

図 4.3: 三国志9の主成分バイプロット図

これらの傾向から, 概ね, 知力と武力は別の要素として見られる傾向がある.

4.2 魏・呉・蜀の勢力別ひいき

発表中に視聴者からも指摘があったが, 魏の曹操を主役にした漫画『蒼天航路』の人気を反映して, 従来は悪役であることが多い魏の人物の能力を底上げしたことが, 三國志シリーズのプロデューサーによって語られている45.

三國志シリーズには「相性」というマスクステータス値があり, 主君と配下の値の差で相性が決まるようになっている. 今回参考にしたサイトの中にも相性値を掲載しているものもあったので, それらをもとに登場人物がどこに属するかを分類してステータス値をプロットする. 各人物について, 劉備, 曹操, 孫権(ソンケン), のいずれに最も相性値が近いかによって, 魏・呉・蜀のどれに属するかを判定する46. 散布図で「武力」と「知力」で表したのが , 主要ステータス数値の平均を, 散布図とバイオリン図でそれぞれ表したのが図4.4, 4.5, 4.6, 4.7である.

df_norm_faction <- df_norm %>% filter(!is.na(相性)) %>% group_by(title) %>% 
    group_map(~mutate(.x, 蜀 = abs(相性 - filter(.x, name_id == "劉備")$相性), 
= abs(相性 - filter(.x, name_id == "曹操")$相性), 呉 = abs(相性 - 
            filter(.x, name_id == "孫権")$相性)) %>% pivot_longer(tidyselect::vars_select(names(.), 
        魏, 呉, 蜀), names_to = "faction", values_to = "dist") %>% group_by(name_id) %>% 
        filter(rank(dist) == 1) %>% ungroup, keep = T) %>% bind_rows %>% 
    mutate(faction = factor(faction, levels = c("魏", "蜀", "呉")))
set.seed(42)
df_norm_faction %>% ggplot(aes(x = 相性, y = 武力, color = faction)) + 
    geom_point() + geom_label(aes(label = name_id), data = group_by(df_norm_faction, 
    title, faction) %>% sample_n(2)) + facet_wrap(~title) + theme_document + 
    scale_color_pander()
三国別武力の散布図

図 4.4: 三国別武力の散布図

df_norm_faction %>% ggplot(aes(x = 相性, y = 知力, color = faction)) + 
    geom_point() + geom_label(aes(label = name_id), data = group_by(df_norm_faction, 
    title, faction) %>% sample_n(2)) + facet_wrap(~title) + theme_document + 
    scale_color_pander()
三国別知力の散布図

図 4.5: 三国別知力の散布図

df_norm_faction %>% ggplot(aes(x = 相性, y = total, color = faction)) + 
    geom_point() + geom_label(aes(label = name_id), data = group_by(df_norm_faction, 
    title, faction) %>% sample_n(2)) + facet_wrap(~title) + labs(y = "主要ステータス値平均") + 
    theme_document + scale_color_pander()
三国別主要ステータス値平均の散布図

図 4.6: 三国別主要ステータス値平均の散布図

df_norm_faction %>% ggplot(aes(x = faction, y = total, fill = faction)) + 
    geom_violin(draw_quantiles = c(0.25, 0.5, 0.75)) + facet_wrap(~title) + 
    labs(y = "主要ステータス値平均") + theme_document + scale_fill_pander()
主要ステータス値平均のバイオリン図

図 4.7: 主要ステータス値平均のバイオリン図

ここからわかるのは, 三国志6以前で呉に属する人物のステータスの低さである. 確かに, 三国志2では呉で武力が90を超える人物は孫堅 (90), 孫策(ソンサク) (94), 太史慈(タイシジ) (95), 甘寧(カンネイ) (92) の4名が存在する (ただし孫堅, 孫策は呉の成立前に死亡する)が, 一方で魏・蜀はともに武力が90を超える人物は10名近く存在する. 呉には武勇を示すエピソードのある武将が他にも多くいるが, 周泰(シュウタイ) (85), 呂蒙(リョモウ) (83), 程普(テイフ) (60), 韓当(カントウ) (58), 董襲(トウシュウ) (56) などは他2国の人物と比較しても低く設定されているように見える. 実態として呉の人材が豊富でなかったという話ではなく, 作品ごとの推移でみると最近の作品ほど分布の形が徐々に画一化してきているという意味である.


  1. さらに, 今回参照したページは非公式のものなので, そもそも全ての項目が掲載されているわけではない.↩︎

  2. ただし, 作品によっては人物がある技能をもつかどうかのフラグが大量に掲載されているものがあり, これらも変数に含めた結果寄与率が下がっている可能性もある.↩︎

  3. 三國志:人気歴史ゲームの誕生秘話 シブサワ・コウに聞く - MANTANWEB(まんたんウェブ)↩︎

  4. よって, 実際には各陣営に属していなかった群雄が三国に分類されることもある. 例えば, シリーズを通して董卓曹操と相性値が近く, 公孫瓚(コウソンサン)袁紹(エンショウ)とその配下の人物は劉備や孫権に近い.↩︎