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.

支払意思額(WTP)の推定

コンジョイント分析で推定した部分効用は、そのままでは「効用(util)」という抽象的な単位でしか表現されない。しかし価格も1つの属性としてモデルに含めておけば、「価格の部分効用」を金額の物差しとして使うことで、他の属性の部分効用を金額(円)に換算できる。これを**支払意思額(willingness to pay, WTP)**と呼ぶ。

例えば「防水機能」の部分効用が、価格500円の値上げに相当する部分効用の大きさと同じなら、防水機能に対するWTPは500円である、と解釈する。

価格が線形(連続変数)の場合

価格を連続変数としてモデルに入れ、βprice\beta_{\text{price}}を価格1単位あたりの効用(通常は負)とする。

V=βpriceprice+βfeaturefeature+V = \beta_{\text{price}} \cdot \text{price} + \beta_{\text{feature}} \cdot \text{feature} + \cdots

ある機能(feature)の有無による効用差βfeature\beta_{\text{feature}}を打ち消すのに必要な価格変化Δprice\Delta \text{price}は、効用を一定に保つ条件

βpriceΔprice+βfeature=0\beta_{\text{price}} \cdot \Delta\text{price} + \beta_{\text{feature}} = 0

から

WTPfeature=Δprice=βfeatureβprice=βfeatureβprice\text{WTP}_{\text{feature}} = \Delta\text{price} = -\frac{\beta_{\text{feature}}}{\beta_{\text{price}}} = \frac{\beta_{\text{feature}}}{|\beta_{\text{price}}|}

と求まる。つまり**「機能の部分効用」を「価格1円あたりの負の効用(限界不効用)」で割ることで、金額に換算**できる。

価格がダミーコーディングされた水準の場合(区分線形近似)

実務のCBCでは、価格も複数の水準(例:1,000円・1,500円・2,000円)としてダミー/効果コーディングされることが多く、この場合βprice\beta_{\text{price}}は単一の係数ではなく水準ごとの部分効用{βp1,βp2,}\{\beta_{p_1}, \beta_{p_2}, \dots\}になる。

この場合は、価格の部分効用を区分線形関数とみなし、機能の部分効用βfeature\beta_{\text{feature}}を「打ち消す価格」を**線形補間(linear interpolation)**で求める。

  1. 価格の各水準p1<p2<<pMp_1 < p_2 < \cdots < p_Mとその部分効用βp1>βp2>>βpM\beta_{p_1} > \beta_{p_2} > \cdots > \beta_{p_M}(価格が上がるほど効用は下がる)をプロットする

  2. 基準点の効用からβfeature\beta_{\text{feature}}だけ効用を下げた水準βp=βp1βfeature\beta_{p^*} = \beta_{p_1} - \beta_{\text{feature}}を求める

  3. その効用に対応する価格pp^*を、隣接する2つの価格水準の間で線形補間して求める

  4. WTP=pp1\text{WTP} = p^* - p_1(基準価格からの差分)

実装例

評定型(トラディショナル)コンジョイント分析で使った4属性(価格・容量・ブランド・パッケージ)の部分効用を例に、「ブランドをC社からA社に変えることへのWTP」を線形補間で求める。

import numpy as np
import pandas as pd

# 価格の部分効用(水準ごと)。価格が上がるほど効用が下がるように設定
price_partworths = {
    1000: 1.4,
    1500: 0.0,
    2000: -1.4,
}
# ブランドの部分効用
brand_partworths = {"A社": 0.8, "B社": 0.2, "C社": -1.0}

prices = np.array(sorted(price_partworths.keys()))
utilities = np.array([price_partworths[p] for p in prices])

def price_for_utility(target_utility, prices, utilities):
    # 効用が target_utility になる価格を、価格部分効用の区分線形補間から求める
    # utilitiesは価格の昇順に対して降順(単調減少)である前提
    for i in range(len(prices) - 1):
        u_hi, u_lo = utilities[i], utilities[i + 1]
        if u_lo <= target_utility <= u_hi:
            # (price[i], u_hi) と (price[i+1], u_lo) の間を線形補間
            frac = (u_hi - target_utility) / (u_hi - u_lo)
            return prices[i] + frac * (prices[i + 1] - prices[i])
    raise ValueError("target_utility が価格レンジの外にあります")

base_price = 1000  # 基準価格(ブランドC社)
base_utility = price_partworths[base_price]

delta_brand = brand_partworths["A社"] - brand_partworths["C社"]  # ブランドC社->A社への効用の増分
# 「価格をbase_priceからいくら上げれば、ブランドC社->A社による効用の増分をちょうど打ち消せるか」を求める
target_utility = base_utility - delta_brand

wtp_price = price_for_utility(target_utility, prices, utilities)
wtp = wtp_price - base_price

print(f"ブランドC社 -> A社 の部分効用差: {delta_brand:.2f}")
print(f"打ち消すために必要な価格: {wtp_price:.0f}円")
print(f"WTP(ブランドC社->A社への追加支払意思額): 約{wtp:.0f}円")
ブランドC社 -> A社 の部分効用差: 1.80
打ち消すために必要な価格: 1643円
WTP(ブランドC社->A社への追加支払意思額): 約643円

ブランドをC社からA社に変更することによる効用の増分は、価格を1,500円から上記で計算した価格まで値上げしても許容できる程度の大きさに相当する、と解釈できる。

集計時の注意点

  • 個人ごとにβprice\beta_{\text{price}}の大きさ(価格感度)が異なる場合、単純に平均のWTPを報告すると、価格感度が極端に低い(ほぼ0に近い)少数の回答者のWTPが外れ値として計算全体を歪めることがある。中央値や、個人ごとのWTPの分布を報告する方が望ましい

  • WTPはあくまで「調査上の仮想的な選択に基づく効用の金額換算」であり、実際の支払行動(revealed preference)とは乖離しうる(hypothetical bias)。可能であれば実売データとのキャリブレーションが望ましい

  • 複数の属性変更を同時に行う場合のWTPは、単純な足し算にはならない(加法モデルの範囲では近似的に成り立つが、交互作用がある場合はズレる)

マーケットシミュレーションとの関係

WTPは1属性を単独で動かした場合の近似的な金額換算だが、マーケットシミュレーションで扱ったシェア・オブ・プリファレンス法を使えば、価格変更とシェア変化を同時に見ながら、より正確に「値上げによる減収」と「機能追加による増収」を金額ベースで比較できる。