k-meansクラスタリングにおいて最適なクラスター数を決定する際、エルボー法(Elbow Method)は最も一般的で直感的な手法です。この記事では、Stataを使ってエルボー法を実装し、WSS(Within-cluster Sum of Squares)をもとに最適なクラスター数を決定する方法を詳しく解説します。
## エルボー法とは
エルボー法は、異なるクラスター数でk-meansクラスタリングを実行し、各クラスター数におけるWSS(クラスター内平方和)をプロットする手法です。WSSの減少が急激から緩やかに変わる点(「肘」のように見える点)が最適なクラスター数とされます。
## 完全なコード
以下のコードをStataにコピペして実行してください:
```stata
* K-means クラスタリング:エルボー法による最適クラスター数の決定
* auto.dta を使用
clear all
set more off
* データの読み込み
sysuse auto, clear
* 分析に使用する変数を標準化(price, mpg, weight, length を使用)
* 欠損値を除外
drop if missing(price) | missing(mpg) | missing(weight) | missing(length)
* 標準化のための変数作成
egen zprice = std(price)
egen zmpg = std(mpg) 
egen zweight = std(weight)
egen zlength = std(length)
* WSS結果を保存するマトリックス準備
matrix wss_results = J(10, 2, .)
* k=1から10まで各クラスター数でk-meansを実行しWSSを計算
forvalues k = 1/10 {
    quietly {
        * k-means クラスタリング実行
        cluster kmeans zprice zmpg zweight zlength, k(`k') name(cluster_k`k')
        
        * 各観測値のクラスター重心からの距離の二乗を計算
        tempvar wss_temp
        gen `wss_temp' = 0
        
        * 各クラスターについて重心を計算しWSSを求める
        forvalues c = 1/`k' {
            * クラスターcの重心を計算
            sum zprice if cluster_k`k' == `c'
            local mean_price = r(mean)
            sum zmpg if cluster_k`k' == `c'
            local mean_mpg = r(mean)
            sum zweight if cluster_k`k' == `c'
            local mean_weight = r(mean)
            sum zlength if cluster_k`k' == `c'
            local mean_length = r(mean)
            
            * クラスターc内の各点から重心までの距離の二乗を計算
            replace `wss_temp' = `wss_temp' + ///
                (zprice - `mean_price')^2 + ///
                (zmpg - `mean_mpg')^2 + ///
                (zweight - `mean_weight')^2 + ///
                (zlength - `mean_length')^2 ///
                if cluster_k`k' == `c'
        }
        
        * 総WSSを計算
        sum `wss_temp'
        local total_wss = r(sum)
        
        * マトリックスに結果を保存
        matrix wss_results[`k', 1] = `k'
        matrix wss_results[`k', 2] = `total_wss'
        
        * クラスター変数を削除(次の反復のため)
        drop cluster_k`k' `wss_temp'
    }
    
    display "k = `k' completed"
}
* 結果をデータセットに変換
drop _all
svmat wss_results, names(col)
rename c1 k
rename c2 wss
* WSS値の表示
list
* エルボープロットの作成
twoway connected wss k, ///
    title("Elbow Method for Optimal Number of Clusters") ///
    xtitle("Number of Clusters (k)") ///
    ytitle("Within-cluster Sum of Squares (WSS)") ///
    xlabel(1(1)10)
display ""
display "エルボープロットを確認して、曲線が「肘」のように曲がる点を見つけてください。"
display "その点が最適なクラスター数(k)です。"
```
## 結果の見方
コードを実行すると、k=1から10までのWSS値の表と、エルボープロットが表示されます。プロット上で曲線が急激な減少から緩やかな減少に変わる点(肘のように見える点)が最適なクラスター数です。
## 詳細な解説
### 1. データ準備
```stata
sysuse auto, clear
drop if missing(price) | missing(mpg) | missing(weight) | missing(length)
```
Stataの標準データセットauto.dtaを読み込み、分析に使用する4つの変数(price, mpg, weight, length)に欠損値がある観測値を除外します。
### 2. 変数の標準化
```stata
egen zprice = std(price)
egen zmpg = std(mpg) 
egen zweight = std(weight)
egen zlength = std(length)
```
k-meansクラスタリングでは変数のスケールが結果に大きく影響するため、すべての変数を標準化(平均0、標準偏差1)します。`egen`コマンドの`std()`関数を使用しています。
### 3. 結果保存用マトリックス
```stata
matrix wss_results = J(10, 2, .)
```
WSS結果を保存するため、10行2列のマトリックスを作成します。1列目にクラスター数k、2列目にWSSを保存します。
### 4. メインループ
```stata
forvalues k = 1/10 {
    quietly {
        cluster kmeans zprice zmpg zweight zlength, k(`k') name(cluster_k`k')
        ...
    }
}
```
k=1から10まで、各クラスター数でk-meansクラスタリングを実行します。`quietly`オプションで中間出力を抑制しています。
### 5. WSS計算
```stata
forvalues c = 1/`k' {
    sum zprice if cluster_k`k' == `c'
    local mean_price = r(mean)
    ...
    replace `wss_temp' = `wss_temp' + ///
        (zprice - `mean_price')^2 + ///
        (zmpg - `mean_mpg')^2 + ///
        (zweight - `mean_weight')^2 + ///
        (zlength - `mean_length')^2 ///
        if cluster_k`k' == `c'
}
```
各クラスターについて重心を計算し、各観測値から重心までの距離の二乗和を求めます。これがWSSの定義です。
### 6. データセット変換とプロット
```stata
svmat wss_results, names(col)
rename c1 k
rename c2 wss
twoway connected wss k, ...
```
マトリックスをデータセットに変換し、変数名を設定してからプロットを作成します。`connected`オプションで線とマーカーの両方を表示します。
## 応用のためのヒント
### 他のデータセットに応用する場合
このコードを他のデータセットに応用したい場合は、以下の部分を変更するだけです:
1. **データ読み込み部分**:`sysuse auto, clear` を自分のデータファイルに変更
2. **変数選択部分**:`price mpg weight length` を分析したい変数に変更
3. **クラスター数の範囲**:必要に応じて `forvalues k = 1/10` の範囲を調整
### ChatGPTやClaude等のAIアシスタントを活用する
ご自身のデータや分析要件に合わせてコードを修正したい場合は、このコードをChatGPTやClaude等に貼り付けて「このコードと同じようにして、自分のデータセット(データの詳細を説明)でエルボー法を実行したい」と依頼すると、適切に修正されたコードを提供してもらえます。
例:「このコードと同じようにして、売上データ(変数:売上高、広告費、従業員数)でクラスタリングしたい」など、具体的な変数名や要件を伝えると効果的です。
## まとめ
エルボー法は最適クラスター数決定の標準的手法です。このStataコードを使えば、簡単にエルボープロットを作成し、データに最適なクラスター数を視覚的に判断できます。重要なのはプロットの形状を注意深く観察し、急激な減少から緩やかな減少に変わる点を見つけることです。