dowhy の -401(k) 資格が純金融資産に与える影響を因果的に推測する

0x01. 問題の背景

このケーススタディでは、401(k) 分析からの実際のデータを使用して、因果プールを使用して平均治療効果 (ATE) および条件付き ATE (CATE) を推定する方法を説明します。

この場合のデータは、実際のデータから取得されます。1980 年代初頭、米国政府は従業員が個人の退職貯蓄を増やすために、税金を繰延べた貯蓄オプションをいくつか導入しました。人気のあるオプションは、従業員が給与の一部を個人口座に預け入れることができる 401(k) プランです。ここでの目標は、個々の特性 (特に収入)による変動性を考慮して、純金融資産 (つまり、401(k) 残高と 401(k) 以外の資産の合計) に対する 401(k) 適格性の影響を理解することです。

401(k) プランは雇用主によって提供されるため、それらを提供する会社の従業員のみが対象となります。したがって、私たちは無作為化されていない研究を扱っています。いくつかの要因 (教育レベル、貯蓄の好みなど) が、401(k) プランの適格性と純金融資産に影響を与える可能性があります。

0x02.データ

検討するサンプルは、1991 年の収入とプログラムへの参加に関する調査からのものですサンプルは、参照個人が 25 ~ 64 歳で、少なくとも 1 人が雇用されているが、自営業者はいない世帯で構成されていました。サンプルには 9915 の世帯レコードがあります。各世帯について、家族参照者の 401(k) プランの適格性 (治療)、純金融資産 (結果)、および年齢、収入、家族の規模、教育、結婚状況などの他の共変量を含む 44 の変数が記録されました。具体的には、16 の共変量を検討しました。一部の変数は次のように要約されます。

変数名 タイプ 詳細
e401 処理 401(k) プランの資格
net_tfa 結果 純金融資産(米ドル)
共変量
株式会社 共変量 収入(米ドル)
fsize 共変量 ファミリーサイズ
教育する 共変量 教育(年)
共変量 男性ですか?
デシベル 共変量 確定給付年金
共変量 結婚?
二稼ぎ 共変量 二人の稼ぎ手
共変量 IRAへの参加
ハウン 共変量 家主?
共変量 住宅価格(米ドル)
高額 共変量 ホームエクイティ(米ドル)
モート 共変量 住宅ローン(米ドル)
共変量 高校がない?(ワンホットエンコード)
HS 共変量 高校?(ワンホットエンコード)
smcol 共変量 いくつかの大学?(ワンホットエンコード)

このデータセットは、'hdm https://rdrr.io/cran/hdm/man/pension.html'__ R パッケージからオンラインで公開されています。実験をより便利にするために、一連の実験の後、データは実験のためにローカルにダウンロードされます。データの取得方法の詳細については、まとめブログ: hdm data R言語取得チュートリアルを参照してください。

0x03.実験

0x03_1. 読み取りデータ

import pandas as pd
df = pd.read_csv("data/pension.csv")
df.head()

データの結果は次のとおりです。

イラ a401 モート 高額 ニファ net_nifa tfa net_tfa tfa_he tw 株式会社 fsize 教育する デシベル 二稼ぎ すべて 91 e401 p401 HS smcol 発明 ecat ザット net_n401 ハウン i1 i2 i3 i4 i5 i6 i7 a1 a2 a3 a4 a5
0 0 0 69000 60150 8850 100 -3300 100 -3300 5550 53550 31 28146 5 12 0 1 0 0 1 0 0 0 0 1 0 0 3 2 0.273178 -3300 1 0 0 1 0 0 0 0 0 1 0 0 0
1 0 0 78000 20000 58000 61010 61010 61010 61010 119010 124635 52 32634 5 16 0 0 0 0 1 0 0 0 0 0 0 1 4 4 0.386641 61010 1 0 0 0 1 0 0 0 0 0 0 1 0
2 1800年 0 200000 15900 184100 7549 7049 9349 8849 192949 192949 50 52206 3 11 0 1 1 1 1 0 0 1 1 0 0 0 6 1 0.533650 8849 1 0 0 0 0 0 1 0 0 0 0 1 0
3 0 0 0 0 0 2487 -6013 2487 -6013 -6013 -513 28 45252 4 15 0 1 0 1 1 0 0 0 0 0 1 0 5 3 0.324319 -6013 0 0 0 0 0 1 0 0 1 0 0 0 0
4 0 0 300000 90000 210000 10625 -2375 10625 -2375 207625 212087 42 33126 3 12 1 0 0 0 1 0 0 0 0 1 0 0 4 2 0.602807 -2375 1 0 0 0 1 0 0 0 0 0 1 0 0

0x03_2. 因果グラフの作成

e401 を治療として、net_tfa を out_come として、その他の共変量を交絡因子として使用すると、因果グラフを作成するコードは次のようになります。

import networkx as nx
import dowhy.gcm as gcm

treatment_var = "e401"
outcome_var = "net_tfa"
covariates = ["age","inc","fsize","educ","male","db",
              "marr","twoearn","pira","hown","hval",
              "hequity","hmort","nohs","hs","smcol"]

edges = [(treatment_var, outcome_var)]
edges.extend([(covariate, treatment_var) for covariate in covariates])
edges.extend([(covariate, outcome_var) for covariate in covariates])

causal_graph = nx.DiGraph(edges)
gcm.util.plot(causal_graph, figure_size=[20, 20])

レンダリングは次のとおりです。
ここに画像の説明を挿入

0x03_3. データ解析

因果モデルを変数に割り当てる前に、ヒストグラムをプロットして変数の分布を把握しましょう。

import matplotlib.pyplot as plt

cols = [treatment_var, outcome_var]
cols.extend(covariates)
plt.figure(figsize=(10,5))
for i, col in enumerate(cols):
    plt.subplot(3,6,i+1)
    plt.grid(False)
    plt.hist(df[col])
    plt.xlabel(col)
plt.tight_layout()
plt.show()

結果は次のようにプロットされます
ここに画像の説明を挿入
。実数値の変数は、ガウス分布などのよく知られたパラメトリック分布に従っていないことがわかります。したがって、これらの変数に親がない場合、カテゴリ変数にも適用される経験的分布に適合します。

0x03_4. データ増加ノイズ強化の堅牢性

因果モデルを変数に割り当てましょう。治療変数については、ランダム フォレスト分類器を使用した分類器の機能的因果モデル (FCM) を割り当てました。結果変数については、関数としてランダム フォレスト回帰を使用する加法性ノイズ モデルとノイズの経験的分布を割り当てました。他の変数には因果グラフに親ノードがないため、経験的分布を割り当てます。

causal_model = gcm.StructuralCausalModel(causal_graph)
causal_model.set_causal_mechanism(treatment_var, gcm.ClassifierFCM(gcm.ml.create_random_forest_classifier()))
causal_model.set_causal_mechanism(outcome_var, gcm.AdditiveNoiseModel(gcm.ml.create_random_forest_regressor()))
for covariate in covariates:
    causal_model.set_causal_mechanism(covariate, gcm.EmpiricalDistribution())

分類子 FCM に適合させるために、処理列を文字列型に変換します。

df = df.astype({
    
    treatment_var: str})

0x03_5. データから因果モデルを当てはめる

gcm.fit(causal_model, df)

出力は次のとおりです。

Fitting causal mechanism of node smcol: 100%|██████████| 18/18 [00:06<00:00,  2.68it/s]

CATE を計算する前に、まず世帯を所得パーセンタイルの等幅ビンに分割します。これにより、さまざまな所得グループへの影響を調べることができます。

import numpy as np

percentages = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]
bin_edges = [0]
bin_edges.extend(np.quantile(df.inc, percentages[1:]).tolist())
bin_edges[-1] += 1 # adding 1 to the last edge as last edge is excluded by np.digitize

groups = [f'{
      
      percentages[i]*100:.0f}%-{
      
      percentages[i+1]*100:.0f}%' for i in range(len(percentages)-1)]
group_index_to_group_label = dict(zip(range(1, len(bin_edges)+1), groups))

これで、CATE を計算できます。これを行うには、あてはめた因果関係プロットの治療変数に対する介入をランダム化し、介入分布からサンプルを抽出し、所得グループごとにグループを観察し、各グループの治療効果を計算します。

np.random.seed(47)

def estimate_cate():
    samples = gcm.interventional_samples(causal_model,
                                         {
    
    treatment_var: lambda x: np.random.choice(['0', '1'])},
                                         observed_data=df)
    eligible = samples[treatment_var] == '1'
    ate = samples[eligible][outcome_var].mean() - samples[~eligible][outcome_var].mean()
    result = dict(ate = ate)

    group_indices = np.digitize(samples['inc'], bin_edges)
    samples['group_index'] = group_indices

    for group_index in group_index_to_group_label:
        group_samples = samples[samples['group_index'] == group_index]
        eligible_in_group = group_samples[treatment_var] == '1'
        cate = group_samples[eligible_in_group][outcome_var].mean() - group_samples[~eligible_in_group][outcome_var].mean()
        result[group_index_to_group_label[group_index]] = cate

    return result

group_to_median, group_to_ci = gcm.confidence_intervals(estimate_cate, num_bootstrap_resamples=100)
print(group_to_median)
print(group_to_ci)

出力は次のとおりです。

{
    
    'ate': 6519.046476486404, '0%-20%': 3985.972442541254, '20%-40%': 3109.9999288096888, '40%-60%': 5731.625707624532, '60%-80%': 7605.467796966453, '80%-100%': 11995.55917989574}
{
    
    'ate': array([4982.99412698, 8339.97497725]), '0%-20%': array([2630.16909916, 5676.94495668]), '20%-40%': array([1252.7312225 , 5215.15452742]), '40%-60%': array([3533.43542901, 8243.86661569]), '60%-80%': array([ 4726.56666574, 10603.23313684]), '80%-100%': array([ 4981.36999637, 19280.14639468])}

信頼区間で示されるように[4982.99, 8339.97]、純金融資産に対する 401(k) 適格性の平均治療効果はプラスです。ここで、明確な全体像を得るために、さまざまな所得グループの CATE をプロットしてみましょう。

fig = plt.figure(figsize=(8,4))
for x, group in enumerate(groups):
    ci = group_to_ci[group]
    plt.plot((x, x), (ci[0], ci[1]), 'ro-', color='orange')
ax = fig.axes[0]
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.xticks(range(len(groups)), groups)
plt.xlabel('Income group')
plt.ylabel('ATE of 401(k) eligibility on net financial assets')
plt.show()

効果は次のとおりです。
ここに画像の説明を挿入
人が低所得層から高所得層に移動するにつれて、効果は増加します。この結果は、所得グループ全体のリソースの制約と一致しているように見えます。

おすすめ

転載: blog.csdn.net/l8947943/article/details/129741232