0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonでp値付き回帰分析+パス解析+介入シミュレーションを実装する

Last updated at Posted at 2025-09-06

ビジネスの現場でデータ分析を行う際、「要因をどう扱うか」が重要になる。

説明変数の中には、自社で制御できるもの(施策・活動) もあれば、制御できないが予測は可能なもの(トレンドや季節性)、さらに制御も予測も難しいもの(競合の動き) も存在する。

e47c08a72a3929b32a1ec54e2d4facaa.png
データ分析の価値は、相関を見つけるだけではなく、

  • どの変数が統計的に有意か(p値による検証)
  • 要因のつながりを整理する(パス解析)
  • 自社の施策を変えた場合どうなるか(介入シミュレーション)

といった観点で、「因果関係を読み解き、意思決定に活かせる形にすること」が重要になる。

240812b637ca516edaf4c8566708f3cd.png

今回扱う分析は、単回帰と重回帰が組み合わさった形 になっています。

  • Education → Income
    • 1つの説明変数で目的変数を説明する典型的な 単回帰 のケース。
  • Income, Education → Health
    • 複数の説明変数を用いて目的変数を説明する 重回帰 のケース。

本記事でのパス解析は、
「単回帰でシンプルな因果を確認し、その後、重回帰によって複数要因が絡む因果を整理する」
という流れになっています。

単回帰と重回帰を組み合わせることで、因果関係をより立体的に捉えられるようになります。

本記事では、Python(scikit-learn)を用いて、p値付き回帰分析からパス解析、さらに介入シミュレーションまでを実装します。

ノートを通じて得られる学び

  • 機械学習の回帰分析を統計的に補強する方法
  • 因果関係を意識したパス解析の考え方
  • 介入シミュレーションを通じた「データで未来を予測する」

モジュールの読み込み

  • データ分析・回帰モデル・可視化に必要なライブラリを読み込み。
  • Ridge は scikit-learn の線形回帰モデルの一種で、正則化付きの回帰分析ができる。
import pandas as pd
import numpy as np
import scipy.stats as stats

from sklearn.linear_model import Ridge

import matplotlib.pyplot as plt
import seaborn as sns

データセットの読み込み

  • CSVデータを pandas で読み込み
  • 最初の数行を確
  • 分析対象は「教育(Education)」「収入(Income)」「健康(Health)」を含むデータセット
df = pd.read_csv('data12_quantitative_health.csv')

print(df.head())

(出力結果)
9ce2f7f5aad82cc29e7ba640c5f43db9.png

p値の計算用の関数

scikit-learn の回帰モデルは係数や切片は出せるが、p値を標準で計算できない。
そのため下記関数を使用しまとめて出力

  • 係数(coeffs)
  • 標準誤差(std_err)
  • t値(t_value)
  • p値(p_value)
    ※統計的な有意性をチェックするための補助ツールです。
'''
p値の計算
- 引数 : 
    - 学習済みモデル : model
    - 説明変数 : X
    - 目的変数 : y
- 戻値 : 
    - p値 : p_values
    - 係数: coeffs
    - 標準誤差: std_err
    - t値: t_values
'''
def calculate_p_values(model, X, y):
    params = np.append(model.intercept_, model.coef_)
    predictions = model.predict(X)
    newX = pd.DataFrame({'Constant': np.ones(len(X))}).join(pd.DataFrame(X.reset_index(drop=True)))
    MSE = (sum((y.values.flatten()-predictions.flatten())**2)) / (len(newX) - len(newX.columns))
    var_b = MSE * (np.linalg.inv(np.dot(newX.T, newX)).diagonal())
    sd_b = np.sqrt(var_b)
    ts_b = params / sd_b
    columns = ['Constant'] + list(X.columns)
    p_values = [2 * (1 - stats.t.cdf(np.abs(i), (len(newX) - 1))) for i in ts_b]
    return pd.DataFrame({'Parameter': columns, 'coeffs': params, 'std_err': sd_b, 't_value': ts_b, 'p_value': p_values})

  • scikit-learn の回帰モデル(例: LinearRegression, Ridge など)に対して、統計的な p値 を計算する関数
  • scikit-learn の回帰モデルは「係数(coef_)や切片(intercept_)」は出してくれますが、t値やp値は標準では出力されない

パス解析

aa1854a35699075022e06dbf59783673.png
今回の例では以下の因果パスを想定します:

  • Education → Income
  • Education, Income → Health
    このパス図に基づいて、それぞれの回帰モデルを実装していきます。

パス解析(1つ目のパス)

Incomeが目的変数、Educationが説明変数。

「教育(Education)」が「収入(Income)」に与える影響をモデル化しています。
切片・係数・決定係数 (R²) を確認し、さらに calculate_p_values で有意性もチェックします。

# 説明変数と目的変数
X = df[['Education']]
y = df[['Income']]

# 線形回帰モデルの作成
income_model = Ridge(alpha=0.001)
income_model.fit(X, y)

# モデルの係数と切片
print(f"切片: {income_model.intercept_}")
print(f"係数: {income_model.coef_}")

# 決定係数 (R^2) の出力
decision_coefficient = income_model.score(X, y)
print(f"決定係数 (R^2): {decision_coefficient}")

(出力結果)
60a3deca5da31632c4c50cf3caa38f9d.png

# p値
p_values_df = calculate_p_values(income_model, X, y)
print(p_values_df)

(出力結果)
3427220ec93df5149750e544b291ad6c.png

パス解析(2つ目のパス)

Healthが目的変数、EducationとIncomeが説明変数。

  • 「教育(Education)」と「収入(Income)」が「健康(Health)」に与える影響を分析
  • 係数・決定係数・p値を確認し、どの変数が有意に寄与しているかを見極める。
# 説明変数と目的変数
X = df[['Income','Education']]
y = df[['Health']]

# 線形回帰モデルの作成
health_model = Ridge(alpha=0.001)
health_model.fit(X, y)

# モデルの係数と切片
print(f"切片: {health_model.intercept_}")
print(f"係数: {health_model.coef_}")

# 予測
y_pred = health_model.predict(X)

# 決定係数 (R^2) の出力
decision_coefficient = health_model.score(X, y)
print(f"決定係数 (R^2): {decision_coefficient}")

(出力結果)
60a3deca5da31632c4c50cf3caa38f9d.png

# p値
p_values_df = calculate_p_values(health_model, X, y)
print(p_values_df)

f8b87389f16443b6b99c2f4ead8ad8de.png

介入

  • 「教育年数を2年間延ばしたら、収入や健康にどう影響するか?」をシミュレーションするための介入処理。
  • 因果推論でよく使われる「もし教育が増えたら…?」というシナリオ分析を行う

(介入の流れ)

  1. Educationを+2に設定
  2. Educationが+2になった場合のIncomeを予測
  3. Educationが+2になった場合Incomeを前提にHealthを予測

EducationからIncomeを予測

  • Educationのデータに+2に設定。
  • income_model(一つ目の線形回帰モデル)``df_intervened['Education']にインプットして、predict(予測)する。
    -incomeを予測する
# 介入:Educationの値を全員に対して増加させる
df_intervened = df.copy()
df_intervened['Education'] = df['Education'] + 2

# 介入後の予測
predicted_income = income_model.predict(df_intervened[['Education']])
df_intervened['Income'] = predicted_income

EducationとIncome(予測値)からHealthを予測

  • health_model(2つ目の線形回帰モデル)``df_intervened[['Income', 'Education']]の2つの説明変数をインプットして、predict(予測)する。
    -Healthを予測する
# 介入後の予測
predicted_post_intervention = health_model.predict(df_intervened[['Income', 'Education']])

元データと介入シナリオとの比較

  • 介入前と介入後の「健康(Health)」の分布を比較。
  • 教育を伸ばした場合、平均的に健康がどのように変化するかを確認。
  • 可視化(KDEプロット)を使うことで、青(介入前)とオレンジ(介入後)の分布の違いを直感的に把握。
# 結果の比較
```comparison = pd.DataFrame({
    'Pre-Intervention': df['Health'].values,
    'Post-Intervention': predicted_post_intervention.flatten()
})

print(comparison.describe())

(出力結果)
2年間の教育が長い方が収入が増えている
f5201280e1045bb72ed3f5395c3c91fa.png

# 分布の可視化
sns.kdeplot(
    comparison['Pre-Intervention'], 
    label='Pre-Intervention', 
    fill=True,
    bw_adjust=2
)
sns.kdeplot(
    comparison['Post-Intervention'], 
    label='Post-Intervention', 
    fill=True,
    bw_adjust=2
)
plt.legend()
plt.title('Health Distribution Before and After Intervention')
plt.xlabel('Health')
plt.ylabel('Density')
plt.show()

(出力結果)
ヒストグラムで確認すると、分布に変化が発生。

  • 青が介入前
  • オレンジが介入後
    62802e2c4c4a689bb1f9ab233aa8422a.png

重要性のポイント

  1. モデル精度だけでは不十分

    • 機械学習や回帰モデルは「予測の当たりやすさ」を出してくれる
    • でも実務では「その結果に意味があるのか?」まで考えないと、施策につながらない
    • 有意性(p値チェック)が必要

  2. 相関と因果は違う

    • 「変数AとBに相関がある」=「AがBの原因」ではない
    • パス解析のように因果関係を整理してこそ、正しい意思決定につながる
    • 因果整理の重要性

  3. 意思決定に直結する「介入」

    • 実務で最も知りたいのは「施策を変えたらどうなるか」
      • 介入シミュレーションで「教育を増やしたら健康が改善する」などの未来を試算できる
      • データ分析が「施策立案の武器」になる

まとめて言うと

本記事では以下を実装

  • scikit-learnで不足しているp値を補う関数の作成
  • 回帰モデルを用いたパス解析の実装
  • 教育施策を仮想的に変えた場合の介入シミュレーション

データ分析は単にモデルを作るだけでなく、有意性を確認し、因果を整理し、介入の効果をシミュレーションすることで意思決定に活かせる

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?