多変量分散分析 (MANOVA)って何?
MANOVA(多変量分散分析)は、複数の連続的な従属変数に対して、独立変数(主にカテゴリ変数)のグループ間で平均値に差があるかを同時に検定する手法です。これは、各従属変数を個別にANOVA(分散分析)する場合、各検定で第Ⅰ種誤差(偽陽性)のリスクが増える問題を、一括して検定することで解決するメリットがあります。
MANOVAの基本的な考え方
- 従属変数(アウトカム)
- 通常、連続変数(例:血圧、血中成分、歩行距離など)が対象となります。
- 複数の従属変数間に相関がある場合、MANOVAはその相関も考慮して検定を行います。
- 独立変数(因子)
- 主にカテゴリ変数(例:治療群、性別、重症度グループなど)を用います。
- 複数の独立変数がある場合も利用できます。ただし、独立変数が連続の場合は、通常の回帰分析(またはMANCOVA:共変量を含むMANOVA)が適用されることが多いです。
- 適用例
- 独立変数1つ、従属変数が複数の場合
たとえば、ある治療法(A群 vs. B群)による効果を、収縮期血圧、拡張期血圧、コレステロール値という複数のアウトカムで評価する場合。
- 独立変数が複数、従属変数も複数の場合
例として、性別と治療群という2要因が、複数の生化学的指標に及ぼす影響を同時に検討する場合などが考えられます。
医学的な具体例:治療群による血圧・コレステロールの変化
例の設定
- 独立変数
- 従属変数
- 収縮期血圧(Systolic Blood Pressure)
- 拡張期血圧(Diastolic Blood Pressure)
- コレステロール値(Cholesterol)
この例では、治療法によってこれらのアウトカムに違いがあるかをMANOVAで検定します。
PythonによるMANOVAの例
以下は、Python(statsmodelsライブラリ)を用いたシンプルなシミュレーション例です。
import numpy as np
import pandas as pd
from statsmodels.multivariate.manova import MANOVA
# 乱数の再現性を確保
np.random.seed(0)
# サンプル数(各群25例、計50例)
n = 50
# 仮想データの作成
# 治療A群と治療B群でアウトカムに差がある設定(例としてA群はやや高め)
data = pd.DataFrame({
'Treatment': np.repeat(['A', 'B'], n/2),
'SystolicBP': np.concatenate([
np.random.normal(130, 10, int(n/2)), # A群
np.random.normal(120, 10, int(n/2)) # B群
]),
'DiastolicBP': np.concatenate([
np.random.normal(85, 8, int(n/2)), # A群
np.random.normal(80, 8, int(n/2)) # B群
]),
'Cholesterol': np.concatenate([
np.random.normal(210, 20, int(n/2)), # A群
np.random.normal(190, 20, int(n/2)) # B群
])
})
print("シミュレーションデータの先頭部分:")
print(data.head())
# MANOVAによる解析:独立変数Treatmentが3つの従属変数に影響を及ぼすか?
manova_model = MANOVA.from_formula('SystolicBP + DiastolicBP + Cholesterol ~ Treatment', data=data)
print("\nMANOVAの結果:")
print(manova_model.mv_test())
コードのポイント
- データ作成
Treatment
が独立変数として扱われ、2つのグループ(A, B)に分類されています。
- 従属変数として、
SystolicBP
(収縮期血圧)、DiastolicBP
(拡張期血圧)、Cholesterol
(コレステロール値)を用意しています。
- ここでは治療A群はやや高めの値を持つように乱数を設定して、群間の差が検出できるようにしています。
- MANOVA解析
statsmodels.multivariate.manova.MANOVA
を用いて、独立変数(Treatment)の効果が、3つの従属変数のセットに対して統計的に有意かどうかを検定します。
まとめ
- MANOVAは、複数の連続従属変数に対して、1つまたは複数のカテゴリカルな独立変数の影響を一括して検定する手法です。
- 独立変数は通常カテゴリ変数ですが、場合によっては連続変数を共変量として含めるMANCOVAもあります。
- 従属変数は連続変数が対象となり、複数のアウトカム間の相関を考慮できます。
- 医療の例では、例えば治療群(カテゴリ変数)が血圧やコレステロールなどの生理学的指標(連続変数)に及ぼす影響を同時に検討する際に有用です。
このように、MANOVAは複数のアウトカムをまとめて解析できるため、単一のアウトカムだけでなく、全体としてのパターンを把握したい場合に非常に有用です。
複数の従属変数のどれに差があってどれに差がないのか、有意差の有無(p値)がわかるってこと?それとも、どれかに差があることしかわからないの?
MANOVAは、まず「全体としての群間の差があるかどうか」を検定する方法です。つまり、複数の従属変数をひとまとめにして、全体としての効果が統計的に有意かどうかを判断します。
MANOVAの結果からわかること:
- MANOVAの全体検定(例:PillaiのTrace, Wilksのλなどの統計量)は、独立変数のグループ間で「従属変数の組み合わせ」に違いがあるかを示します。
- この全体検定が有意であれば、少なくともどれかの従属変数に群間差があることを示唆しますが、どの従属変数がどの程度差を生んでいるかは直接明らかにしません。
個別の従属変数ごとの差を知るには:
- 全体検定が有意であった場合、通常は各従属変数について個別にANOVA(または他の方法)を行って、どの変数が差に寄与しているかを評価する「事後解析」や「フォローアップ解析」を行います。
具体例で説明
たとえば、治療群AとBにおいて、収縮期血圧、拡張期血圧、コレステロール値の3つのアウトカムを同時に評価する場合、MANOVAでは以下の2点がわかります。
- 全体検定
「治療群によって、3つの生理学的指標の組み合わせに有意な差があるか?」
これが有意ならば、どれか1つ以上の指標が群間で差を持っている可能性が高いと示唆されます。
- 各従属変数の寄与
MANOVAの結果だけでは「収縮期血圧には差があるが、拡張期血圧とコレステロールは差がない」とは直接は分かりません。
そのため、個別にANOVAなどを行い、各アウトカムのp値を確認する必要があります。
Pythonでの例(前回のコードに続いて)
# MANOVAの全体検定結果は前述のコードの結果として出力されます。
# 例えば、各従属変数ごとに個別のANOVAを実施する場合
import statsmodels.api as sm
import statsmodels.formula.api as smf
# 収縮期血圧のANOVA
model_systolic = smf.ols('SystolicBP ~ Treatment', data=data).fit()
anova_systolic = sm.stats.anova_lm(model_systolic, typ=2)
print("\n収縮期血圧のANOVA:")
print(anova_systolic)
# 拡張期血圧のANOVA
model_diastolic = smf.ols('DiastolicBP ~ Treatment', data=data).fit()
anova_diastolic = sm.stats.anova_lm(model_diastolic, typ=2)
print("\n拡張期血圧のANOVA:")
print(anova_diastolic)
# コレステロールのANOVA
model_cholesterol = smf.ols('Cholesterol ~ Treatment', data=data).fit()
anova_cholesterol = sm.stats.anova_lm(model_cholesterol, typ=2)
print("\nコレステロールのANOVA:")
print(anova_cholesterol)
このように、まずMANOVAで全体として群間差があるかを調べ、次に個別のANOVAで各従属変数の寄与を評価する流れとなります。
まとめ
- MANOVAの全体検定:複数の従属変数の組み合わせにおける群間差の有無を検出する。
- 個別の検定:どの従属変数に群間差があるかを明確にするには、事後に個別のANOVAなどで検証する必要がある。
これにより、MANOVAは全体的なパターンを捉えるのに有用ですが、詳細な変数ごとの違いを理解するためには追加の解析が必要です。
従属変数3つに関して、どれも有意差がないけれど、従属変数3つからつくったコンポジットな指標(ある疾患の病勢の指標)に関してなら有意差が出るということってありえる?
はい、あり得ます。各従属変数が個別に見ると効果が小さく、統計的に有意な差が検出されない場合でも、これらの変数を組み合わせたコンポジット指標は、各変数の小さな効果を累積して全体のばらつきを低減し、統計的検出力を高めることがあるため、有意な差が出る可能性があります。
たとえば、ある疾患の病勢を評価する際に、BNP、NTproBNP、6分間歩行距離といった個々のマーカーでは群間差が微小であっても、これらを適切に標準化して重み付けや単純な加算でコンポジットスコアを作成すると、各マーカーの情報が統合され、全体としての差が明確になる場合があります。
つまり、個別の指標では有意な差が認められなくても、全体を捉える指標(コンポジットスコア)では有意な差が出る可能性があるということです。
独立変数が連続変数なら、通常の多変量回帰分析?
独立変数が連続の場合、複数の従属変数に対して同時に回帰分析を行う「多変量回帰分析(multivariate multiple regression)」が適用されます。
これは、たとえば以下のような医療分野の例で説明できます。
具体例:年齢とBMIが複数のバイタルサインに与える影響
例の設定
- 独立変数(説明変数)(連続変数)
- 従属変数(アウトカム)(連続変数)
- SystolicBP(収縮期血圧)
- DiastolicBP(拡張期血圧)
- Cholesterol(コレステロール値)
- BloodSugar(血糖値)
この例では、年齢とBMIがこれら4つのバイタルサインにどのように影響しているかを、同時に検討します。各アウトカムは連続変数であり、複数の従属変数間には相関がある可能性があります。これにより、個々に回帰分析するよりも全体としてのモデルの有用性を評価できます。
Pythonによるシミュレーションと多変量回帰分析
以下のコードは、100人分の仮想データを生成し、独立変数(Age, BMI)が従属変数(SystolicBP, DiastolicBP, Cholesterol, BloodSugar)に与える影響を多変量回帰分析(MANOVAを利用)で解析する例です。
import numpy as np
import pandas as pd
from statsmodels.multivariate.manova import MANOVA
import statsmodels.api as sm
import statsmodels.formula.api as smf
# 乱数の再現性を確保
np.random.seed(42)
# サンプル数
n = 100
# 仮想データの作成
# 年齢は20〜80歳、BMIは18〜35の範囲で生成
data = pd.DataFrame({
'Age': np.random.uniform(20, 80, n),
'BMI': np.random.uniform(18, 35, n)
})
# 従属変数をシミュレーション(それぞれに少しのランダムな誤差を加える)
# 各アウトカムは、AgeとBMIの線形結合を仮定して生成
data['SystolicBP'] = 90 + 0.5 * data['Age'] + 1.2 * data['BMI'] + np.random.normal(0, 5, n)
data['DiastolicBP'] = 60 + 0.3 * data['Age'] + 0.8 * data['BMI'] + np.random.normal(0, 4, n)
data['Cholesterol'] = 150 + 0.4 * data['Age'] + 2.0 * data['BMI'] + np.random.normal(0, 10, n)
data['BloodSugar'] = 80 + 0.2 * data['Age'] + 1.5 * data['BMI'] + np.random.normal(0, 6, n)
print("仮想データの先頭部分:")
print(data.head())
# MANOVAを用いた多変量回帰分析
# 複数の従属変数をまとめて解析することで、AgeとBMIが全体としてアウトカムに影響を及ぼすかを検定
manova_formula = 'SystolicBP + DiastolicBP + Cholesterol + BloodSugar ~ Age + BMI'
manova_model = MANOVA.from_formula(manova_formula, data=data)
manova_results = manova_model.mv_test()
print("\nMANOVAの結果:")
print(manova_results)
# 各従属変数について個別に回帰分析も実施(補足的な解析)
print("\n各アウトカムごとの個別回帰分析:")
models = {}
for outcome in ['SystolicBP', 'DiastolicBP', 'Cholesterol', 'BloodSugar']:
formula = f'{outcome} ~ Age + BMI'
model = smf.ols(formula, data=data).fit()
models[outcome] = model
print(f"\n【{outcome} の回帰結果】")
print(model.summary())
コードの説明
- データ生成
- サンプル数100例を想定し、独立変数として年齢(Age)とBMIを乱数で生成。
- 各従属変数(収縮期血圧、拡張期血圧、コレステロール、血糖値)は、AgeとBMIの線形結合にランダムノイズを加えてシミュレーション。
- MANOVAによる多変量回帰
MANOVA.from_formula
を用いて、式 'SystolicBP + DiastolicBP + Cholesterol + BloodSugar ~ Age + BMI'
により、両独立変数が4つのアウトカムに対してどのような全体的影響を与えるかを一括検定します。
- 結果から、全体としての効果の有意性(全体検定のp値)を確認できますが、個々の従属変数にどの程度影響があるかは別途個別解析が必要です。
- 個別回帰分析
- 補足的に、各従属変数ごとにOLS回帰モデルを構築し、AgeとBMIの影響を個別に確認します。
まとめ
- 多変量回帰分析(Multivariate Multiple Regression)
- 独立変数が連続の場合でも、複数の連続従属変数に対して同時に解析を行うことで、全体としてのモデルの有用性を評価できます。
- この方法は、各従属変数間の相関を考慮しながら、共通の予測因子(ここではAgeとBMI)が複数のアウトカムに与える影響を一度に検証できるメリットがあります。
- 医療分野では、年齢やBMIなどの連続的なリスク因子が、血圧、コレステロール、血糖値などの複数の健康指標に与える影響を調べる際に有用です。
このように、独立変数が連続の場合でも、多変量回帰分析によって複数の従属変数との関係性を一括で評価することが可能です。
つまりMANOVAは、独立変数が連続でもカテゴリでもどちらでも使えるってこと?
概ねその通りです。ただし、少し補足があります。
通常、MANOVAは複数の連続従属変数に対して、独立変数(因子)が群ごとに効果を持つかどうかを検定する手法で、伝統的にはカテゴリカルな独立変数を対象としています。しかし、実際の解析ツール(たとえばstatsmodelsなど)では、連続の独立変数を含めることも可能です。この場合、解析は実質的に**多変量回帰分析(multivariate multiple regression)**と同じ方法論になります。
つまり、
- 独立変数がカテゴリの場合:群間の差を一括で検定するためのMANOVAとして使う。
- 独立変数が連続の場合:複数の従属変数に対して連続的な予測因子の効果を評価する多変量回帰分析として扱えるが、統計的手法としては同じ枠組みで解析できる(場合によってはMANCOVAとも呼ばれることがある)。
要するに、解析の数学的枠組みは同じですが、独立変数がカテゴリか連続かで解釈のニュアンスが変わるという点に注意してください。
独立変数が連続の場合、カットオフ価を決めて、高値、低値の2群(つまりカテゴリ変数)にするというのは、あり?それでMANOVAを適用するとか。
カットオフで連続変数を2群に分けること自体は可能ですが、注意が必要です。
- メリット:
- 臨床的に意味のあるカットオフがある場合、解釈がしやすくなります。
- グループごとの比較が明確になり、結果の提示がシンプルになります。
- デメリット:
- 連続変数を2群に分けると、情報の一部が失われ、統計的検出力が低下する可能性があります。
- カットオフの選び方が恣意的になると、結果の再現性や解釈に問題が生じる可能性もあります。
もし、カットオフに医学的・臨床的な根拠があるのであれば、そのグループ分けでMANOVAを適用するのは一つの方法です。
ただし、元の連続データを活かして多変量回帰分析(あるいは連続独立変数としてのMANOVA)を行うことも検討すべきです。どちらのアプローチが適切かは、研究の目的やデータの性質に依存します。
なるほど、たしかにカットオフ値を決める根拠がないのなら、無意味になるね。
その通りです。カットオフ値を設定する場合は、事前に臨床的または統計的根拠が必要です。根拠がないと、情報の損失や誤った解釈につながる可能性があります。連続変数の情報を最大限活用するためには、可能な限り連続のままで解析する(例えば多変量回帰分析)方が一般的に望ましいと言えます。