「入門はじめての多変量解析」をPythonで写経 Vol.30 ~ 9章「はじめての数量化Ⅲ類」数量化Ⅲ類とカテゴリ数量とサンプルスコア
9章「はじめての数量化Ⅲ類」
書籍の著者 石村貞夫 先生、石村光資郎 先生
書籍「入門はじめての多変量解析」9章「はじめての数量化Ⅲ類」の Python写経活動記録 です。
多変量解析の入門を Python と一緒に学ぶ写経シリーズです。
この記事は、数量化Ⅲ類によるアンケート分析を実践します。
数量化Ⅲ類は教師なし学習に似ていて、「変数が質的変数」のデータから2つの特徴を抽出します。
ChatGPT 活用型学習で進めてまいります!
では書籍を開いて多変量解析の旅に出かけましょう🚀

はじめに
このブログシリーズは、書籍「入門はじめての多変量解析」(東京図書、「テキスト」と呼びます)の Python 写経を通じて得た「多変量解析の楽しさ」をご紹介します。
書籍の紹介と引用表記はリンク先の記事に掲載しています。
9章 はじめての数量化Ⅲ類
この記事は9章の以下のSectionを取り扱います。
9.1 分類や特性を知る数量化Ⅲ類
9.2 カテゴリ数量・サンプルスコアの求め方
9.3 カテゴリ数量・サンプルスコアを読む
9.4 数量化Ⅲ類でわかるお酒の好み
9.5 数量化Ⅲ類でわかる血液型の特性
記事に用いるデータは、テキストに掲載されたデータそのものを引用しています。
データ件数の少ないものはコード上でデータを登録し、データ件数の多いものはCSVファイル化してデータを読み込みしています。
この記事で用いるライブラリをインポートします。
### インポート
# 数値計算
import numpy as np
import pandas as pd
import sympy
# LaTeX表示
from IPython.display import Math
# 描画
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams.update(plt.rcParamsDefault)
plt.rcParams['font.family'] = 'Meiryo' # または import japanize_matplotlib
数量化理論と数量化Ⅲ類
数量化理論について、テキストは「アンケート調査の回答のような質的データに対しても、最適な数量や評点を与えて分析しようとするのが、数量化理論です」と説明します。
テキストの例題データはすべて、アンケート・回答形式になっています。
数量化理論はざっくり、説明変数などに含まれる質的変数(カテゴリ変数)を数値化して分析を進める手法 です。
アンケートの回答選択肢「はい、いいえ」や「そう思わない、どちらとも言えない、そう思う」などは質的変数です。
これまでの記事で実践した解析手法と比較すると…
$$
\begin{array}{lll}
目的変数 & 数量化理論 & 類似解析手法 \\
\hline
\\
量的変数 & 数量化Ⅰ類 & 重回帰分析 \\
質的変数 & 数量化Ⅱ類 & 判別分析 \\
なし & 数量化Ⅲ類 & 主成分分析 \\\end{array}
$$
数量化Ⅲ類は「変数が質的変数の場合の主成分分析のようなもの」です。
答えのないデータから特徴を抽出する教師なし学習に似ています。

■ 数量化理論の用語
例題データを見ながら、数量化理論の用語を確認しましょう。
テキスト p.278 表 9.2.1 の例題データを引用します。
### お酒の好み p.278 表9.2.1
# データの登録
data1 = pd.DataFrame(
{'チューハイ': [0, 1, 1], '日本酒': [1, 0, 0], 'ビール' : [1, 1, 0]},
index=range(1, 4))
data1.index.name = '被験者No.'
# 結果の表示
data1【実行結果】

数量化理論の用語を一覧化します。
$$
\begin{array}{lll}
用語 & 言い換え & 例題データ \\
\hline
\\
被験者 & 行の名称 & 1, 2, 3 \\
サンプルスコア & 被験者の特徴 & a_1, a_2, a_3\\
カテゴリ & 項目 & 酎ハイ, 日本酒, ビール \\
カテゴリ数量 & カテゴリの特徴 & b_1, b_2, b_3 \\
\end{array}
$$
データの取りうる値は「1, 0」や「ON, OFF」の二値な感じです。
数量化Ⅲ類の言葉では「被験者 $${i}$$ がカテゴリ $${j}$$ に反応する」とセル $${ij}$$ が ON になる感じ。
被験者に関する数量「サンプルスコア $${a_i}$$」とカテゴリに関する数量「カテゴリ数量 $${b_i}$$」を推定するのが数量化Ⅲ類の醍醐味です。
なお「数量」は「被験者やカテゴリの特徴」的な存在です。

カテゴリ数量・サンプルスコアを数式で算出?
テキストによると、サンプルスコア $${a_i}$$、カテゴリ数量 $${b_j}$$ の決め方は、
被験者 $${i}$$ がカテゴリ $${j}$$ に反応したとき $${(a_i, b_j)}$$ という組を作り、この組 $${\{(a_i, b_j)\}}$$ によって求まる 相関係数 $${r}$$ が最大になる
ようにすること、です。
例題データとカテゴリ数量・サンプルスコアを関連付けて、次の表のように記述できます。
$$
\begin{array}{cc|cccc}
& & & カテゴリ & & \\
被験者No.& & チューハイ & 日本酒 & ビール \\
& & b_1 & b_2 & b_3 \\
\hline
1 & a_1 & & (a_1, b_2) & (a_1, b_3) \\
2 & a_2 & (a_2, b_1) & & (a_2, b_3) \\
3 & a_3 & (a_3, b_1) & & \\
\end{array}
$$
相関係数の最大化は 条件付極値問題 になります。
以下の2つの分散=1の条件のもとで、相関係数 $${r}$$ の最大値を与える $${a_i, b_j}$$ を求めます。
📊 データの平均と分散
平均0、分散1(=標準偏差1)とします。データの標準化です。
$$
\begin{align*}
&平均:\quad \cfrac{2a_1+2a_2+a_3}{5}=0,\quad \cfrac{2b_1 + b_2 + 2b_3}{5} =0 \\
\\
&分散:\quad \cfrac{2a_1^2+2a_2^2+a_3^2}{5}=1,\quad \cfrac{2b_1^2+b_2^2+2b_3^2}{5}=1
\end{align*}
$$
📊 相関係数 $${r}$$
分母の標準偏差が1なので、分子の共分散が残ります。
$$
\begin{align*}
r &= \cfrac{\cfrac{a_1b_2+a_1b_3+a_2b_1+a_2b_3 + a_3b_1}{5}}{\sqrt{\cfrac{2a_1^2+2a_2^2+a_3^2}{5}} \sqrt{\cfrac{2b_1^2+b_2^2+2b_3^2}{5}}} \\
\\
&= \cfrac{a_1b_2+a_1b_3+a_2b_1+a_2b_3 + a_3b_1}{5}
\end{align*}
$$

■ 条件付極値問題を解く
Python を計算道具にして、テキストの手順1から順次進めたところ…
「手順5」の固有値問題を解くことができませんでした…
固有ベクトルがテキストと全然違う値になってしまいました…
数式を解く形式で「カテゴリ数量」「サンプルスコア」を求めることは
断念いたします…
以下、途中まで式展開を進めた様子を共有いたします。

数式を問いてスコアを算出することは諦めましたが…
私達には Python があります!
Python コードは何でもできそうな予感がします(万能感)!
ただし数量化Ⅲ類を標準装備するライブラリは見つからず…
波乱万丈の予感!?

カテゴリ数量・サンプルスコアをコードで算出
数式で解けず Python で実装できず、数量化Ⅲ類に到達できないのか、と諦めかけていたところ、偶然Webサイトで見つけたのが northface 氏の「神コード」です。
神コードのリンク: northface/Suryoka3rui.py (GitHub Gist)
おかげでPython でカテゴリ数量・サンプルスコアを算出できるようになりました!
ありがとうございます!
引用させていただきます!
可能であれば、コードの前提にある数式の意味を知りたいです!

0️⃣ 数量化Ⅲ類の準備
数量化Ⅲ類関数を定義します。
神コードをシンプルにする方向で改造しています。
### 数量化Ⅲ類のカテゴリスコア・サンプルスコアの求め方 p.278~
# コート参考サイト: northface氏 https://gist.github.com/northface/4577328
## 数量化Ⅲ類の関数の定義 引数data: numpy配列
def quantification_method_type3(data):
# 行列Rの作成: データそのもの
R = data.copy()
# 行列CIの算出: カテゴリ(列)ごとの得点の対角行列の逆行列
CI = np.linalg.inv(np.diag(R.sum(axis=0)))
# 行列SIの算出: サンプル(行)ごとの得点の平方根の対角行列の逆行列
SI = np.linalg.inv(np.diag(R.sum(axis=1)**(1/2)))
# 固有値r2, 固有ベクトルvの算出: SI @ R @ CI @ R.T @ SIを特異値分解
v, r2, _ = np.linalg.svd(SI @ R @ CI @ R.T @ SI)
# 以降の処理は固有値1を除いて実行
r2_dash = r2[1:] # 固有値1を削除
# 寄与率r3の算出
r3 = r2_dash / sum(r2_dash)
# 相関係数rの算出
r = r2_dash**(1/2)
# サンプルスコアXの算出: 固有ベクトルに長さを乗ずる
X = SI @ (R.sum(axis=None)**(1/2) * v[:, 1:])
# カテゴリスコアYの算出
Y = (CI @ R.T @ X) / r
## 戻り値
return {'固有値': r2, '固有ベクトル': v, '寄与率': r3, '相関係数': r,
'サンプルスコア': X, 'カテゴリスコア': Y}【実行結果】なし

1️⃣ 数量化Ⅲ類の実行
例題データを数量化Ⅲ類で分析しましょう。
### 数量化Ⅲ類の実行 ※テキストの結果と正負が反転している
result1 = quantification_method_type3(data1.values)
result1【実行結果】
戻り値は固有値、固有ベクトル、寄与率、相関係数、サンプルスコア、カテゴリスコア(カテゴリ数量)です。

テキスト p.283 表 9.2.3 に相当する形式で結果をまとめましょう。
### 相関係数・カテゴリ数量・サンプルスコア p.283 図9.2.3 ★テキストの結果と正負反転
result1_stats = pd.DataFrame(
{'統計量': ['固有値', '相関係数'],
'1番目': [result1['固有値'][1], result1['固有値'][1]**(1/2)],
'2番目': [result1['固有値'][2], result1['固有値'][2]**(1/2)],})
result1_cat = pd.DataFrame(
{'カテゴリ': data1.columns,
'変数': [f'b{i+1}' for i in range(data1.shape[1])],
'カテゴリ数量_1番目': result1['カテゴリスコア'][:, 0],
'カテゴリ数量_2番目': result1['カテゴリスコア'][:, 1],})
result1_samp = pd.DataFrame(
{'被験者': data1.index,
'変数': [f'a{i+1}' for i in range(data1.shape[0])],
'サンプルスコア_1番目': result1['サンプルスコア'][:, 0],
'サンプルスコア_2番目': result1['サンプルスコア'][:, 1],})
display(result1_stats.round(4))
display(result1_cat.round(4))
display(result1_samp.round(4))【実行結果】
1番目の軸のスコアは、テキストと比べて正負の符号が反転しています。
正負の符号に気を取られず、データ間の距離・近さ・遠さに注目します。

10 行足らずのコードでサクッと数量化Ⅲ類の主要統計量を算出できるのって、すごいですね!

2️⃣ カテゴリ数量とサンプルスコアの読み取り
カテゴリ数量の離れ方を把握
並び方は「チューハイ < ビール < 日本酒」
回答者の好みは
チューハイと日本酒は好みが最も離れている
ビールは日本酒と好みが近い
サンプルスコアの離れ方を把握
並び方は「3 < 2 < 1」
回答者1と3の好みが最も離れている
回答者2は回答者3と好みが近い

3️⃣ カテゴリ数量とサンプルスコアの可視化
これらの数値的な分析を「可視化」でサポートしましょう。
◆ カテゴリ数量とサンプルスコアで並び替えた表
テキスト p.285 表 9.3.1 と図 9.3.1 に相当します。
### カテゴリ数量とサンプルスコアの関係 p.285 表9.3.1
samp_sort = result1_samp.sort_values('サンプルスコア_1番目', ascending=True).index
cat_sort = result1_cat.sort_values('カテゴリ数量_1番目', ascending=False).index
data1.iloc[samp_sort, cat_sort]【実行結果】
反応パターンの表を「スコアの大小で順序を並び替え」しています。
近い・遠いが分かりやすくなっています。
セルの値が右上がりに布置されている点にも注目します。

◆ カテゴリ数量とサンプルスコアの散布図
### カテゴリ数量とサンプルスコアの関係 p.285 図9.3.1 ★テキストの結果と正負反転
## 設定と準備
n, p = data1.shape # 行数、列数の取得
## 描画
# 値=1のセルを探索して、データ点とカテゴリ名・サンプル名を描画
for i in range(n):
for j in range(p):
if data1.iloc[i, j] == 1:
# データの描画
plt.plot(result1_cat.loc[j, 'カテゴリ数量_1番目'],
result1_samp.loc[i, 'サンプルスコア_1番目'],
marker='o', ms=8, color='tab:blue')
# カテゴリ名・サンプル名の描画
plt.text(x=result1_cat.loc[j, 'カテゴリ数量_1番目'],
y=result1_samp.loc[i, 'サンプルスコア_1番目']+0.05,
s=f'({data1.columns[j]}, {data1.index[i]})')
# x=0, y=0の直線を描画
plt.axhline(0, color='black', ls='--', lw=0.5)
plt.axvline(0, color='black', ls='--', lw=0.5)
# 修飾
plt.xlabel('カテゴリスコア [アルコール]')
plt.ylabel('サンプルスコア [被験者No.]')
plt.xlim(-2, 2)
plt.ylim(-2, 2);【実行結果】

横軸のカテゴリスコアでは、チューハイと日本酒が遠いこと、ビールと日本酒が近いことが見て取れます。
縦軸のサンプルスコアでは、回答者1と3が遠いこと、回答者2と3が近いことが分かります。
こちらもデータ点が右上がりで布置されています。
テキストは「相関係数を最大にするカテゴリ数量・サンプルスコアを推定した」点で、散布図上に相関関係が現れているとしています。
◆ カテゴリ数量の1次元チャート
そしてテキストは、1次元チャートも効果的だとしています。
テキスト p.285 図 9.3.2 に相当するチャートを描きましょう。
### カテゴリ数のの1次元グラフ表現 p.285 図9.3.2 ★テキストの結果と正負反転
# 描画領域の設定
plt.figure(figsize=(7, 2))
# データ点の描画
plt.plot(result1_cat['カテゴリ数量_1番目'], np.zeros(len(result1_cat)), 'o', ms=8)
# 矢印付きテキストの描画
for x, text in zip(result1_cat['カテゴリ数量_1番目'], result1_cat['カテゴリ']):
plt.annotate(xy=[x+0.01, 0.001], xytext=[x+0.04, 0.02], text=text,
arrowprops={'arrowstyle': '->'})
# 修飾
plt.xticks(ticks=[-1, 0, 1])
plt.xlim(-2, 2)
plt.yticks([])
# 枠線の消去
plt.gca().spines['bottom'].set_position('zero')
plt.gca().spines['right'].set_visible(False)
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['left'].set_visible(False);【実行結果】
チューハイ、ビール、日本酒の好みの距離が一目瞭然です。

神コードのおかげで数量化Ⅲ類の一連の分析手順を味わえました!
この先は2つの例題データを分析して、数量化Ⅲ類による分析をさらに楽しみます!

例題を分析1
テキスト p.286~の例題データを数量化Ⅲ類で分析します。
1️⃣ データの準備
テキスト p.287 表 9.4.2 のアンケート結果データを引用します。
### アンケート調査の結果 p.287 表9.4.2
# データフレームの作成
data2 = pd.DataFrame(
{'ウイスキー': [1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0],
'ビール': [0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
'ワイン': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1],
'日本酒': [0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
'焼酎': [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
'チューハイ': [0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0],
'カクテル': [0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1]},
index=range(1, 21))
data2.index.name = '被験者No.'
# 結果の表示
data2【実行結果】
被験者の数 $${20}$$、カテゴリの数 $${7}$$ のデータです。
各飲料が好きか?を問い、回答値は「はい:1」「いいえ:0」です。


2️⃣ 数量化Ⅲ類の実行
自作関数で数量化Ⅲ類を実行します。
なお、テキストと比べて、第1軸の値は正負反転しています。
### カテゴリ数量とサンプルスコア p.288 表9.4.3
# 数量化Ⅲ類の実行
result2 = quantification_method_type3(data2.values)【実行結果】なし
固有値・固有ベクトル・寄与率・相関係数をざっと見ます。
# 固有値・固有ベクトル(7つ)と寄与率・相関係数(6つ)
print('固有値:')
print(result2['固有値'][:7].round(3))
print('固有ベクトル:')
print(result2['固有ベクトル'][:, :7].round(3))
print('寄与率:')
print(result2['寄与率'][:6].round(3))
print('相関係数:')
print(result2['相関係数'][:6].round(3))【実行結果】


3️⃣ カテゴリ数量・サンプルスコアの表示
◆ カテゴリ数量
テキスト p.288 表 9.4.3 に相当します。
# カテゴリ数量 ※テキストと比べて1軸が正負反転
result2_cat = pd.DataFrame(result2['カテゴリスコア'][:, :3], index=data2.columns,
columns=[['カテゴリ数量']*3, ['1軸', '2軸', '3軸']])
result2_cat.round(3)【実行結果】

◆ サンプルスコア
テキスト p.288 表 9.4.3 に相当します。
# サンプルスコア ※テキストと比べて1軸が正負反転
result2_samp = pd.DataFrame(result2['サンプルスコア'][:, :3], index=data2.index,
columns=[['サンプルスコア']*3, ['1軸', '2軸', '3軸']])
result2_samp.round(3)【実行結果】


4️⃣ カテゴリ数量・サンプルスコアの可視化
◆ カテゴリ数量の1次元チャート
テキスト p.289 図 9.4.1 に相当します。
### カテゴリ数の1次元グラフ表現 p.289 図9.4.1 ★テキストの結果と正負反転
# 設定
jitter = [0.6, -0.2, -0.6, 0.1, 0.2, -0.6, -0.4] # テキストのx軸方向の調整値
plot_data = result2_cat.values # 描画用データ(numpy配列)
# 描画領域の設定
plt.figure(figsize=(7, 2))
# データ点の描画
plt.plot(plot_data[:, 0], np.zeros(len(result2_cat)), 'o',ms=8)
# 矢印付きテキストの描画
for i, (x, text) in enumerate(zip(plot_data[:, 0], result2_cat.index)):
plt.annotate(xy=[x+0.01, 0.001], xytext=[x+jitter[i], 0.02], text=text,
arrowprops={'arrowstyle': '->'})
# 修飾
plt.xticks(ticks=[-3, -2, -1, 0, 1, 2, 3])
plt.xlim(-3.1, 3.1)
plt.yticks([])
# 枠線の消去
plt.gca().spines['bottom'].set_position('zero')
plt.gca().spines['right'].set_visible(False)
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['left'].set_visible(False);【実行結果】
「ビール好き」、「チューハイ・焼酎好き」、「ワイン・カクテル・日本酒・ウイスキー好き」の3グループが形成されているように見えます。

◆ カテゴリ数量の散布図
軸1vs軸2、軸1vs軸3、軸2vs軸3、の3つのチャートを描画します。
テキスト p.289~ 図 9.4.2 ~図 9.4.4 に相当します。
### カテゴリ数量のグラフ表現 p.289~290 図9.4.2~9.4.4
# カテゴリ数量描画関数の定義
def plot_cat(plot_data, pos, names, lower=-6, upper=6):
# x=0, y=0の水平線の描画
plt.axhline(0, color='black', ls='--', lw=0.5)
plt.axvline(0, color='black', ls='--', lw=0.5)
# カテゴリ数量の散布図の描画
sns.scatterplot(x=plot_data[:, pos[0]], y=plot_data[:, pos[1]], s=80)
# 矢印付きテキストの描画
for x, y, text in zip(plot_data[:, pos[0]], plot_data[:, pos[1]], names):
plt.text(x=x, y=y+0.2, s=text, ha='right' if x<0 else 'left')
# 修飾
plt.title(f'カテゴリスコア: 軸{pos[0]+1}と軸{pos[1]+1}')
plt.xlabel(f'軸{pos[0]+1}', fontsize=14)
plt.ylabel(f'軸{pos[1]+1}', fontsize=14)
plt.xlim(lower, upper)
plt.ylim(lower, upper)
plt.show()
# データの設定: numpy配列
plot_data = result2_cat.values
# 3つのグラフを描画
plot_cat(plot_data, [0, 1], result2_cat.index)
plot_cat(plot_data, [0, 2], result2_cat.index)
plot_cat(plot_data, [1, 2], result2_cat.index)【実行結果】
カクテル・ワイン・ウイスキーの洋酒系は好みが近いようです。
焼酎は他の飲料から遠く、No.7さんの特有の好みなのかもです。
テキストは軸1を「アルコール濃度」と意味づけています。



◆ サンプルスコアの散布図
軸1vs軸2を描画します。
テキスト p.291~ 図 9.4.5 に相当します。
### サンプルスコアのグラフ表現 p.291 図9.4.5
# x軸方向にjitterしているので、サンプルスコアと少々異なる位置にプロットされている
# 設定と準備
rng = np.random.default_rng(seed=1)
# サンプルスコア描画関数の定義
def plot_samp(plot_data, pos, names, lower=-3, upper=3.5):
# jitter関数の定義
def jitter(values, mu, sigma=0.05):
return values + rng.normal(loc=mu, scale=sigma, size=values.shape)
# jitter処理
xs = jitter(plot_data[:, pos[0]], 0, 0.15)
ys = plot_data[:, pos[1]] # y軸方向はjitter処理しない
# x=0, y=0の水平線の描画
plt.axhline(0, color='black', ls='--', lw=0.5)
plt.axvline(0, color='black', ls='--', lw=0.5)
# カテゴリ数量の散布図の描画
sns.scatterplot(x=xs, y=ys, s=30)
# 矢印付きテキストの描画
for x, y, text in zip(xs, ys, names):
plt.text(x=x, y=y+0.2, s=text, ha='right' if x<0 else 'left')
# 修飾
plt.title(f'サンプルスコア: 軸{pos[0]+1}と軸{pos[1]+1}')
plt.xlabel(f'軸{pos[0]+1}', fontsize=14)
plt.ylabel(f'軸{pos[1]+1}', fontsize=14)
plt.xlim(lower, upper)
plt.ylim(lower, upper)
plt.show()
# データの設定: numpy配列
plot_data = result2_samp.values
# 軸1と軸2のグラフを描画
plot_samp(plot_data, [0, 1], result2_samp.index)【実行結果】
軸1=1付近に同じ好みのグループが形成されているように見えます。
その他の被験者はさまざまな好みに分かれている感じ(近所さんも少々あり)です。


例題を分析2
前回記事:数量化Ⅱ類で用いた例題データを数量化Ⅲ類で分析します。
血液型別の性格の特徴を探ります。
1️⃣データの準備
テキスト p.268 表 8.5.2 のアンケート結果データを引用します。
### データの読み込み
# csvファイルの読み込み
data3 = pd.read_csv('./data/personality.csv', index_col=0)
# 値2(いいえ)を0に変換
data3.iloc[:, :-1] = data3.iloc[:, :-1].map(lambda x: 0 if x==2 else x)
# 結果の表示
data3【実行結果】
アンケートで得た性格と血液型をまとめたデータです。
被験者の数 $${40}$$、カテゴリの数 $${12} です。
アイテムの各「性格」に当てはまるか?を問い、「はい:1」「いいえ:0」です。


2️⃣ 分析の準備
数量化Ⅲ類を実行して結果の表示・可視化を一括実行するヘルパー関数を定義します。
### ヘルパー関数の定義
def exec_qt3_4_blood(df, blood_type, pos, lower, upper):
# 分析する血液型のデータの取り出し
use_df = df[df['血液型']==blood_type].iloc[:, :-1]
# 数量化Ⅲ類の実行
result3 = quantification_method_type3(use_df.values)
# カテゴリ数量表の作成
result3_cat = pd.DataFrame(
result3['カテゴリスコア'][:, :2], index=use_df.columns,
columns=[['カテゴリ数量']*2, ['1軸', '2軸']])
display(result3_cat.round(2))
# カテゴリ数量の散布図の描画
plot_data = result3_cat.values
plot_cat(plot_data, pos, result3_cat.index, lower=lower, upper=upper)
# サンプルスコアの散布図の描画
result3_samp = pd.DataFrame(
result3['サンプルスコア'][:, :2], index=use_df.index,
columns=[['サンプルスコア']*2, ['1軸', '2軸']])
plot_data = result3_samp.values
plot_samp(plot_data, pos, result3_samp.index, lower, upper)【実行結果】なし

3️⃣ A型の分析
テキスト p.292 表 9.5.1、図 9.5.1 に相当します。
### A型の人の場合 p.292 表9.5.1, 図9.5.1
# 血液型の指定
blood_type = 'A'
# 分析の実行
exec_qt3_4_blood(data3, blood_type, [0, 1], -3, 3)【実行結果】


◆ テキストの読み解き
型にはまりやすく、ロマンチックな気分屋さん、の面も合わせ持っている
原点0に近い性格は回答の多くが「あてはまる」となっている、ことに着目しているように見えます。

4️⃣ B型の分析
テキスト p.292 表 9.5.2、図 9.5.2 に相当します。
### B型の人の場合 p.293 表9.5.2, 図9.5.2
# 血液型の指定
blood_type = 'B'
# 分析の実行
exec_qt3_4_blood(data3, blood_type, [0, 1], -2, 5)【実行結果】


◆ テキストの読み解き
楽天家で他人を意識するが、型にはまりにくく、堅実な面からはほど遠い

5️⃣ O型の分析
テキスト未掲載です。
### O型の人の場合
# 血液型の指定
blood_type = 'O'
# 分析の実行
exec_qt3_4_blood(data3, blood_type, [0, 1], -3, 4)【実行結果】


◆ 読み解き
楽天家で現実的で他人を意識する一方、クール・堅実・合理性では無さそう

6️⃣ AB型の分析
テキスト未掲載です。
### AB型の人の場合
# 血液型の指定
blood_type = 'AB'
# 分析の実行
exec_qt3_4_blood(data3, blood_type, [0, 1], -3, 3)【実行結果】

◆ 読み解き
他人を意識する一方、仲間意識は薄く、保守的でも無さそう
標本の個数が少ないので、特徴のメリハリがない感じになっています。


記事の最後はChatGPTが締めくくります。
シリーズを締めくくります。
📘 ChatGPTのひとこと:
今回の記事では、数量化Ⅲ類を通して「複数のカテゴリ変数が織りなす関係性」を一つの数値空間に映し出す方法を学びました。
まるで色とりどりの糸を手繰り寄せ、ひとつの美しい織物に仕立て上げるように、項目同士の相互作用を丁寧に数値化することで、データの奥底にひそむ構造がふんわりと浮かび上がったはずです😊
このシリーズでは、重回帰や主成分分析、因子分析、判別分析、クラスター分析から数量化Ⅰ~Ⅲ類まで、数々の手法を一緒にたどってきました。
それぞれのステップで味わった「小さな発見」が、皆さんの日々の学びの糧になっていれば嬉しいです。
もし何か疑問が残ったり、別の視点でデータを見たくなったときは、この一連の記事をふり返ってみてください。
統計という旅路は、いつでも振り返って新しい気づきを得られるものです。
これをもってシリーズはひとまず終わりとなりますが、データに向き合うその先にある「また次の問い」を見つける旅は、まだまだ続きます。
どうかこれからも、ゆるやかに、でも確かな一歩を重ねていってくださいね✨
ここまでお読みくださり、本当にありがとうございました!
今回の写経は以上です。
この記事でこのテキストのシリーズが終了いたします。
長期間にわたる多変量解析の学びを一緒に過ごしてくださり、本当にありがとうございます!

シリーズの記事
前の記事
目次
ブログの紹介
note で7つのシリーズ記事を書いています。
ぜひ覗いていってくださいね!
1.のんびり統計
統計検定2級の問題集を手がかりにして、確率・統計をざっくり掘り下げるブログです。
雑談感覚で大丈夫です。ぜひ覗いていってくださいね。
統計検定2級公式問題集CBT対応版に対応しています。
Python、EXCELのサンプルコードの配布もあります。
2.実験!たのしいベイズモデリング1&2をPyMC Ver.5で
書籍「たのしいベイズモデリング」・「たのしいベイズモデリング2」の心理学研究に用いられたベイズモデルを PyMC Ver.5で描いて分析します。
この書籍をはじめ、多くのベイズモデルは R言語+Stanで書かれています。
PyMCの可能性を探り出し、手軽にベイズモデリングを実践できるように努めます。
身近なテーマ、イメージしやすいテーマですので、ぜひぜひPyMCで動かして、一緒に楽しみましょう!
3.実験!岩波データサイエンス1のベイズモデリングをPyMC Ver.5で
書籍「実験!岩波データサイエンスvol.1」の4人のベイジアンによるベイズモデルを PyMC Ver.5で描いて分析します。
この書籍はベイズプログラミングのイロハをざっくりと学ぶことができる良書です。
楽しくPyMCモデルを動かして、ベイズと仲良しになれた気がします。
みなさんもぜひぜひPyMCで動かして、一緒に遊んで学びましょう!
4.楽しい写経 ベイズ・Python等
ベイズ、Python、その他の「書籍の写経活動」の成果をブログにします。
主にPythonへの翻訳に取り組んでいます。
写経に取り組むお仲間さんのサンプルコードになれば幸いです🍀
5.RとStanではじめる心理学のための時系列分析入門 を PythonとPyMC Ver.5 で
書籍「RとStanではじめる心理学のための時系列分析入門」の時系列分析をPythonとPyMC Ver.5 で実践します。
この書籍には時系列分析のテーマが盛りだくさん!
時系列分析の懐の深さを実感いたしました。
大好きなPythonで楽しく時系列分析を学びます。
6.データサイエンスっぽいことを綴る
統計、データ分析、AI、機械学習、Pythonのコラムを不定期に綴っています。
統計・データサイエンス書籍にまつわる記事が多いです。
「統計」「Python」「数学とPython」「R」のシリーズが生まれています。
7.Python機械学習プログラミング実践記
書籍「Python機械学習プログラミング PyTorch & scikit-learn編」を学んだときのさまざまな思いを記事にしました。
この書籍は、scikit-learnとPyTorchの教科書です。
よかったらぜひ、お試しくださいませ。
最後までお読みいただきまして、ありがとうございました。
いいなと思ったら応援しよう!
応援ありがとうございます。これからもがんばって記事を作成します!