Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

評定型(トラディショナル)コンジョイント分析

評定型コンジョイント分析(rating-based / traditional conjoint analysis) は、回答者に個々のプロファイル(属性の組み合わせ)を1つずつ提示し、「どの程度好ましいか」を評点(例:1〜7点のリッカート尺度、0〜100点の購入意向)で回答させる、最も古典的なコンジョイント分析の方式である。

得られた評点を目的変数、各属性の水準をダミー変数化した説明変数として 線形回帰(OLS) を行うことで、部分効用を推定する。

モデル

回答者がプロファイルiiに与える評点yiy_iを以下のように表すとする。

yi=β0+k=1Kl=1Lk1βkldkl(i)+εi,εiN(0,σ2)y_i = \beta_0 + \sum_{k=1}^{K} \sum_{l=1}^{L_k - 1} \beta_{kl}\, d_{kl}(i) + \varepsilon_i, \quad \varepsilon_i \sim N(0, \sigma^2)

ここで

  • dkl(i)d_{kl}(i):属性kkの水準llに対応する符号化変数

  • βkl\beta_{kl}:その水準の部分効用

  • β0\beta_0:切片(全体平均効用)

ダミーコーディングと効果コーディング

属性はカテゴリ変数なので、回帰に使う前に数値化する必要がある。代表的な方式が2つある。

  • ダミーコーディング(dummy coding):ある水準を基準(リファレンス)として0/10/1で表す。基準水準の部分効用は0に固定され、他の水準の係数は基準水準からの差分として解釈される。

  • 効果コーディング(effects coding):基準水準を-1、対象水準を+1、その他を0で表す。

この符号化では

l=1Lkβkl=0(各属性 k について)\sum_{l=1}^{L_k} \beta_{kl} = 0 \quad (\text{各属性 } k \text{ について})

という制約のもとで各水準の部分効用が推定されるため、切片β0\beta_0がプロファイル全体の平均効用として解釈できる。

コンジョイント分析では、部分効用を「属性内水準の平均からの乖離」として解釈したいことが多く、水準間の比較が基準水準に依存しない効果コーディングが標準的に用いられる。

属性重要度

各属性kkの部分効用の値域(レンジ)

rangek=maxlβklminlβkl\text{range}_k = \max_l \beta_{kl} - \min_l \beta_{kl}

を全属性で正規化したものを、属性の相対的な重要度とする。

Importancek=rangekj=1Krangej\text{Importance}_k = \frac{\text{range}_k}{\sum_{j=1}^{K} \text{range}_j}

実装例

4属性からなる架空の飲料製品について、真の部分効用を設定してプロファイルへの評点データを生成し、効果コーディング+OLSで部分効用を復元できるか確認する。

import itertools
import numpy as np
import pandas as pd

rng = np.random.default_rng(0)

attributes = {
    "価格":     ["1,000円", "1,500円", "2,000円"],
    "容量":     ["500ml", "1000ml"],
    "ブランド":  ["A社", "B社", "C社"],
    "パッケージ": ["缶", "瓶", "ペットボトル"],
}

# 真の部分効用(各属性内の和が0になるように設定)
true_partworths = {
    "価格":     {"1,000円": 1.5, "1,500円": 0.0, "2,000円": -1.5},
    "容量":     {"500ml": -0.5, "1000ml": 0.5},
    "ブランド":  {"A社": 0.8, "B社": 0.2, "C社": -1.0},
    "パッケージ": {"缶": -0.3, "瓶": 0.6, "ペットボトル": -0.3},
}
intercept_true = 5.0

profiles = list(itertools.product(*attributes.values()))
df = pd.DataFrame(profiles, columns=attributes.keys())

def true_utility(row):
    return intercept_true + sum(
        true_partworths[attr][row[attr]] for attr in attributes
    )

df["true_utility"] = df.apply(true_utility, axis=1)
df["rating"] = df["true_utility"] + rng.normal(0, 0.3, size=len(df))
df.head()
Loading...
# 効果コーディング(各属性の最終水準を基準とし、-1/0/+1で符号化)
def effects_code(df, attributes):
    X = pd.DataFrame(index=df.index)
    for attr, levels in attributes.items():
        base = levels[-1]  # 最終水準を基準に
        for level in levels[:-1]:
            col = f"{attr}::{level}"
            X[col] = 0
            X.loc[df[attr] == level, col] = 1
            X.loc[df[attr] == base, col] = -1
    return X

X = effects_code(df, attributes)
X.insert(0, "intercept", 1)
X.head()
Loading...
import statsmodels.api as sm

model = sm.OLS(df["rating"], X)
result = model.fit()
result.summary()
Loading...
# 基準水準の部分効用は、他の水準の推定値の符号反転和として復元する
coef = result.params.drop("intercept")

partworths_hat = {"intercept": result.params["intercept"]}
for attr, levels in attributes.items():
    attr_coefs = {
        level: coef[f"{attr}::{level}"]
        for level in levels[:-1]
    }
    base_level = levels[-1]
    attr_coefs[base_level] = -sum(attr_coefs.values())
    partworths_hat[attr] = attr_coefs

pd.DataFrame(partworths_hat)
Loading...

推定された部分効用β^\hat\betaは、ノイズの範囲内で真の部分効用(価格:1.5 / 0.0 / -1.5、容量:-0.5 / 0.5、ブランド:0.8 / 0.2 / -1.0、パッケージ:-0.3 / 0.6 / -0.3、切片:5.0)を概ね再現できている。

# 属性重要度
importance = {}
for attr, levels in attributes.items():
    values = list(partworths_hat[attr].values())
    importance[attr] = max(values) - min(values)

total = sum(importance.values())
importance_pct = {k: v / total for k, v in importance.items()}
pd.Series(importance_pct).sort_values(ascending=False).rename("importance")
価格 0.435710 ブランド 0.282776 パッケージ 0.143118 容量 0.138396 Name: importance, dtype: float64

評定型コンジョイント分析の限界

  • 個々のプロファイルを独立に評価させるため、属性間のトレードオフ(選好の一貫性)が反映されにくい(実際の購買では選択肢の中から1つを選ぶ相対比較が起きる)

  • 評点尺度の使い方に回答者間で個人差がある(scale usage heterogeneity)

  • 属性数・水準数が多いと、提示するプロファイル数が増え回答負荷が高くなる

これらの限界から、実務では 選択型コンジョイント分析(CBC) が主流になっている。