Pythonで推しをクラスター分析してみた

はじめに

注意事項

これは統計解析やプログラミングの指南ではありません。オタクの自己分析です。

着想に至った経緯

長くオタクをやっていると、何となく色々なジャンルで似たキャラを好きになる気がする……でもどんなキャラが好きか上手く言い表せない。そこでキャラの情報を数値化し、プログラムに客観的に分類させようと試みました。
Pythonは学生の頃から便利なお手伝いさん感覚で使っていた程度です。仕事では必要に応じて色々なモジュールを使うようにはなりましたが、あまり複雑なことはやっていません。したがってここで使用するコードもごく単純なものとなります。

分析方法

使用言語

Python 3.11.4

分析手法

k平均法によりクラスター分析を行いました。クラスター数を決めるための予備検討としてウォード法による階層的クラスター分析を行いました。また、最終的にどの評価項目の影響が大きかったのか確認するために入力データをランダムフォレストモデルに学習させ、重要度の高い評価項目を抽出しました。

入力データ

推しの名前と各評価項目に対する点数の一覧のCSVデータを使用しました。対象ジャンルは現在のメインであるファイアーエムブレム、原神、アークナイツとし、以下の31人を選定しました。

ファイアーエムブレム(12)
クリフ
クレア
カチュア
パイソン
リュート
ベルクト
フォルデ
ルーテ
エーデルガルト
リンハルト
イングリット
シルヴァン

原神(7)
エウルア
ベネット
北斗
カーヴェ
アルハイゼン
楓原万葉
宵宮

アークナイツ(12)
キアーベ
アオスタ
ブローカ
ホルン
ガヴィル
二アール
フロストリーフ
ワイルドメイン
ケルシー
スカジ
インディゴ
グレースロート

評価項目は以下の11種類とし、5段階で評価しました。
①Intelligence
知性、賢さです。飛び抜けた天才が5、他はどんなに賢くても4です。
②Calm
落ち着きがあるかどうか。
③Activeness
積極性、自主性、活発さなど。
④Freedom
自由度。自由奔放な人は5、規則や伝統に縛られて生きづらそうな人は1です。
⑤Curiosity
好奇心旺盛かどうか。Intelligenceと相関があったりなかったりする指標です。
⑥Delicacy
繊細さ。ここでは人や物事に対する丁寧さも含みます。気配りができる人は点数が高く、豪快な人は低くなっています。
⑦BeautySense
美的センス。お洒落な人や美術的な素養のある人は5、見た目に無頓着な人は1です。
⑧Sociality
ここでは社交性、親しみやすさです。明らかに人付き合いの悪そうな人は1です。
⑨Prudence
慎重さ、用心深さ。疑り深い人は点数が高く、騙されやすい人は低いです。
⑩Kindness
親切さ、面倒見の良さ。所謂ツンデレも点数が高いのでノイズ疑惑があります。
⑪Leadership
リーダーシップ。何らかの組織や団体のトップにいる人は5です。

なお、予備検討として年齢、性別、外見(身長、胸囲、明度、彩度)、ゲーム中での使いやすさを評価項目に加えていましたが、重要ではなさそうだったため削除しました。初めから不要とわかっている次元は削減するに限ります。

実際に読み込ませたデータは以下の通りです。評価点数は私の独断で決めています。

namelist.csv


コード

以下のリンクを参考にしました。今回は自分で整形したデータを使っているのでいくらか手順を端折っています。

わからないことはbingAIに聞きました。AI最高。人類の叡知の結晶。

実際のコードは以下の通りです。何をやっているかは参考リンク先をご確認ください。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import linkage,dendrogram
from sklearn import preprocessing
from sklearn.cluster import KMeans
from sklearn.ensemble import RandomForestClassifier

#csvデータの読み込み
df=pd.read_csv('namelist.csv',header=0)
df=df.set_index('Name')

#データの前処理
ss=preprocessing.StandardScaler()
df_s=pd.DataFrame(ss.fit_transform(df))
df_s.columns=df.columns
df_s.index=df.index

#階層的クラスター分析
df_s_hclust=linkage(df_s,metric='euclidean',method='ward')
plt.figure(figsize=(8,3))
dendrogram(df_s_hclust)
plt.savefig('dendrogram.png')

#k-means法によるクラスター分析
ncl=5
km=KMeans(n_clusters=ncl,n_init=10,random_state=42)
df_ar=df_s.values

#グルーピング配列の出力
df_pred=km.fit_predict(df_ar)
df_KMclust=df.assign(cluster_ID=df_pred)

#重要度の高い項目を3つ抽出
X=df_KMclust.drop('cluster_ID',axis=1)
Y=df_KMclust['cluster_ID']
model=RandomForestClassifier(random_state=42)
model.fit(X,Y)
importances=model.feature_importances_
indices=np.argsort(importances)[::-1]
top_indices=indices[:3]
top_features=df.columns[top_indices]
print(top_features)

#結果の出力
for i in range(0,ncl):
    temp_df=df[df_KMclust['cluster_ID']==i]
    fnamout='result'+str(i)+'.csv'
    temp_df.to_csv(fnamout)

分析結果

階層的クラスター分析

クラスター数を決めるにあたり、一度階層的クラスター分析を行うやり方があります。ここでは参考と同じユークリッド距離、ウォード法で行いました。
結果は以下に示します。1本孤立しているのが気になりますが、クラスター数は5と設定しました。

dendrogram

k平均法によるクラスター分析

5つのグループの内訳を以下に示します。

グループ0

クレア、ベネット、北斗、宵宮、キアーベ、ガヴィル
非常にわかりやすいグループです。積極性、自由度が高く好奇心旺盛です。また社交的で概ね面倒見が良く、人を疑うことを知らない幸せな人たちです。知性は低めの傾向があり、医者のガヴィルも難しいことを考えるのは苦手です。良く言えば元気印、悪く言えばトラブルメーカー。

Group0

グループ1
カチュア、パイソン、リュート、楓原万葉、アオスタ、ブローカ、フロストリーフ、スカジ、インディゴ、グレースロート
比較的落ち着きと慎重さの項目が高く、活発さとリーダーシップが低いグループです。自制心強めのクールな人が多いですね。

Group1

グループ2
クリフ、ルーテ、リンハルト、アルハイゼン
知性と好奇心が飛び抜けており協調性の低いグループです。学者肌です。

Group3

グループ3
カーヴェ
孤立していたのは彼でした。
分類:カーヴェ。

Group4

グループ4
ベルクト、フォルデ、エーデルガルト、イングリット、シルヴァン、エウルア、ホルン、ニアール、ケルシー
並み以上の知性がありお行儀が良く、行動の面ではそこそこいい人そうに見えます。貴族です。不特定多数に対する責任感の強い人たちです。

Group4

ランダムフォレストモデルによる学習と重要項目の抽出

参考リンク先にはないのですが、この中で最も分類に影響していそうなパラメータを抽出する方法はないか? とbingAIに尋ねたところ、以下を提案されました。

#重要度の高い項目を3つ抽出
X=df_KMclust.drop('cluster_ID',axis=1)
Y=df_KMclust['cluster_ID']
model=RandomForestClassifier(random_state=42)
model.fit(X,Y)
importances=model.feature_importances_
indices=np.argsort(importances)[::-1]
top_indices=indices[:3]
top_features=df.columns[top_indices]

top_featuresの出力結果は以下の通りでした。
['Leadership', 'Activeness', 'Prudence']

……グルーピング結果を見たところLeadershipとActivenessは確かに効いていそうです。
ランダムフォレストは機械学習でよく使われる手法のようですが、私は今回初めて知りました。時間のある時に勉強してみようと思います。

まとめ

クラスター数を5とすることで概ね自分の感じている通りの分類になりました。好きなキャラの傾向がはっきりしているようなそうでもないような、とモヤモヤしていたのが少しすっきりした気がします。カーヴェ何だお前。
また、昔のジャンルまで遡ると女性好きというのも特徴としてありそうですが、最近のゲームでは配慮されているキャラクターが多いためか今回は抽出されませんでした。
最近仕事でPythonを使う機会が増えてきてしょうもない遊びも思いつくようになりました。今後も楽しみながら色々なことを学び、自分のために生かしていきたいと思います。

この記事が気に入ったらサポートをしてみませんか?