导入数据¶

In [1]:
import pandas as pd
c0m0full = pd.read_csv(r'D:\论文\最后一波一鼓作气\数据\c0m0full.csv')  
c1m1full = pd.read_csv(r'D:\论文\最后一波一鼓作气\数据\c1m1full.csv')  
hsf15full = pd.read_csv(r'D:\论文\最后一波一鼓作气\数据\hsf15full.csv')  
hsf18full = pd.read_csv(r'D:\论文\最后一波一鼓作气\数据\hsf18full.csv')  
city_gender_age_premium_ratio_district15 = pd.read_csv(r'D:\论文\最后一波一鼓作气\数据\city_gender_age_premium_ratio_district15.csv')  
In [2]:
#删除城市样本
c1m1full = c1m1full[c1m1full['urban_nbs'] != 'Urban']
#确保15年未整合,18年整合了
c1m1full = c1m1full[(c1m1full['policyintergration2015']==0.0) & (c1m1full['policyintergration2018']==1.0)]
c1m1= c1m1full[['ID', 'c1','m1']]

#删除城市样本
c0m0full = c0m0full[c0m0full['urban_nbs'] != 'Urban']
#确保15年未整合,18年整合了
c0m0full = c0m0full[(c0m0full['policyintergration2015']==0.0) & (c0m0full['policyintergration2018']==1.0)]
c0m0= c0m0full[['ID', 'c0','m0']]

#删除城市样本
hsf15full = hsf15full[hsf15full['urban_nbs'] != 'Urban']
#确保15年未整合,18年整合了
hsf15full = hsf15full[(hsf15full['policyintergration2015']==0.0) & (hsf15full['policyintergration2018']==1.0)]
hsf15= hsf15full[['ID', 'hsf15']]

#删除城市样本
hsf18full = hsf18full[hsf18full['urban_nbs'] != 'Urban']
#确保15年未整合,18年整合了
hsf18full = hsf18full[(hsf18full['policyintergration2015']==0.0) & (hsf18full['policyintergration2018']==1.0)]
hsf18= hsf18full[['ID', 'hsf18']]

最优化方法¶

consumption-based:合并数据¶

In [3]:
data = pd.merge(c0m0, c1m1full,on="ID", how="inner")
data
Out[3]:
ID c0 m0 householdID communityID c1 m1 gender age marriage ... premium2018 r0 r1 r0adjust r1adjust policyintergration2015 policyintergration2018 district GDPgrowthrate urban_nbs
0 64033321002 112.216 60.0 640333210 640333 123.670 0.0 0.0 59.0 1.0 ... 180.0 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural
1 64033327002 1029.200 6000.0 640333270 640333 1054.764 21000.0 0.0 62.0 1.0 ... 180.0 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural
2 64033325001 1062.400 3000.0 640333250 640333 78.020 100.0 1.0 66.0 1.0 ... 180.0 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural
3 64033322001 592.620 2000.0 640333220 640333 859.050 17050.0 1.0 63.0 1.0 ... 180.0 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural
4 64033330002 2058.400 2000.0 640333300 640333 4025.500 2000.0 1.0 59.0 1.0 ... 180.0 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3882 89676104001 2315.700 840.0 896761040 896761 891.420 8000.0 1.0 61.0 1.0 ... 220.0 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural
3883 89676114002 1935.145 300.0 896761140 896761 49.800 0.0 0.0 56.0 0.0 ... 220.0 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural
3884 89676118001 2466.096 1000.0 896761180 896761 661.095 3000.0 0.0 73.0 0.0 ... 220.0 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural
3885 89676115001 10721.940 800.0 896761150 896761 11638.260 2000.0 1.0 55.0 1.0 ... 220.0 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural
3886 89676124001 268.422 500.0 896761240 896761 313.242 101.0 1.0 69.0 0.0 ... 220.0 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural

3887 rows × 26 columns

In [9]:
#最优化方法——消费计算
import pandas as pd
import numpy as np

# 计算 E(m0) 和 E(m1)
E_m0 = data['m0'].mean()
E_m1 = data['m1'].mean()

# 计算 E(1/c0) 和 E(1/c1)
E_c0_inv2 = (1/data['c0']).mean()
E_c1_inv2 = (1/data['c1']).mean()

# 计算协方差
cov_c0_inv2 = np.cov((1/data['c0']) / E_c0_inv2, (data['r0'] - data['r1']) * data['m0'] + data['premium2015'] - data['premium2018'])[0, 1]
cov_c1_inv2 = np.cov((1/data['c1']) / E_c1_inv2, (data['r0'] - data['r1']) * data['m1'] + data['premium2015'] - data['premium2018'])[0, 1]

# 计算 gamma
data['gamma312'] = abs(data['premium2015'] - data['premium2018']) + abs(0.5 * (data['r0'] - data['r1']) * (E_m0 + E_m1)) + 0.5 * cov_c0_inv2 + 0.5 * cov_c1_inv2
gamma312= data['gamma312'].mean()
print(gamma312)
data
841.987535959292
Out[9]:
ID c0 m0 householdID communityID c1 m1 gender age marriage ... r1 r0adjust r1adjust policyintergration2015 policyintergration2018 district GDPgrowthrate urban_nbs gamma612 gamma312
0 64033321002 112.216 60.0 640333210 640333 123.670 0.0 0.0 59.0 1.0 ... 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural 652.775511 652.775511
1 64033327002 1029.200 6000.0 640333270 640333 1054.764 21000.0 0.0 62.0 1.0 ... 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural 652.775511 652.775511
2 64033325001 1062.400 3000.0 640333250 640333 78.020 100.0 1.0 66.0 1.0 ... 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural 652.775511 652.775511
3 64033322001 592.620 2000.0 640333220 640333 859.050 17050.0 1.0 63.0 1.0 ... 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural 652.775511 652.775511
4 64033330002 2058.400 2000.0 640333300 640333 4025.500 2000.0 1.0 59.0 1.0 ... 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural 652.775511 652.775511
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3882 89676104001 2315.700 840.0 896761040 896761 891.420 8000.0 1.0 61.0 1.0 ... 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural 701.272074 701.272074
3883 89676114002 1935.145 300.0 896761140 896761 49.800 0.0 0.0 56.0 0.0 ... 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural 701.272074 701.272074
3884 89676118001 2466.096 1000.0 896761180 896761 661.095 3000.0 0.0 73.0 0.0 ... 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural 701.272074 701.272074
3885 89676115001 10721.940 800.0 896761150 896761 11638.260 2000.0 1.0 55.0 1.0 ... 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural 701.272074 701.272074
3886 89676124001 268.422 500.0 896761240 896761 313.242 101.0 1.0 69.0 0.0 ... 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural 701.272074 701.272074

3887 rows × 28 columns

In [10]:
#异质性男性 平衡面板
#最优化方法——消费计算 
datamale = data.loc[data['gender'] == 1].copy()
import pandas as pd
import numpy as np

# 计算 E(m0) 和 E(m1)
E_m0 = datamale['m0'].mean()
E_m1 = datamale['m1'].mean()

# 计算 E(c0^(-2)) 和 E(c1^(-2))
E_c0_inv2 = (1/datamale['c0']).mean()
E_c1_inv2 = (1/datamale['c1']).mean()

# 计算协方差
cov_c0_inv2 = np.cov(1/datamale['c0']/ E_c0_inv2, (datamale['r0'] - datamale['r1']) * datamale['m0'] + datamale['premium2015'] - datamale['premium2018'])[0, 1]
cov_c1_inv2 = np.cov(1/datamale['c1']/ E_c1_inv2, (datamale['r0'] - datamale['r1']) * datamale['m1'] + datamale['premium2015'] - datamale['premium2018'])[0, 1]

# 计算 gamma
datamale['gamma322'] = abs(datamale['premium2015'] - datamale['premium2018']) + abs(0.5 * (datamale['r0'] - datamale['r1']) * (E_m0 + E_m1)) + 0.5 * cov_c0_inv2 + 0.5 * cov_c1_inv2
gamma322= datamale['gamma322'].mean()
print(gamma322)
802.7906600812382
In [11]:
#异质性女性 混合截面
#最优化方法——消费计算 
datafemale = data.loc[data['gender'] == 0].copy()
import pandas as pd
import numpy as np

# 计算 E(m0) 和 E(m1)
E_m0 = datafemale['m0'].mean()
E_m1 = datafemale['m1'].mean()

# 计算 E(c0^(-2)) 和 E(c1^(-2))
E_c0_inv2 = (1/datafemale['c0']).mean()
E_c1_inv2 = (1/datafemale['c1']).mean()

# 计算协方差
cov_c0_inv2 = np.cov(1/datafemale['c0'] / E_c0_inv2, (datafemale['r0'] - datafemale['r1']) * datafemale['m0'] + datafemale['premium2015'] - datafemale['premium2018'])[0, 1]
cov_c1_inv2 = np.cov(1/datafemale['c1'] / E_c1_inv2, (datafemale['r0'] - datafemale['r1']) * datafemale['m1'] + datafemale['premium2015'] - datafemale['premium2018'])[0, 1]

# 计算 gamma
datafemale['gamma332'] = abs(datafemale['premium2015'] - datafemale['premium2018']) + abs(0.5 * (datafemale['r0'] - datafemale['r1']) * (E_m0 + E_m1)) + 0.5 * cov_c0_inv2 + 0.5 * cov_c1_inv2
gamma332= datafemale['gamma332'].mean()
print(gamma332)
881.1201345894027
In [12]:
import numpy as np
import pandas as pd

# —— 异质性条件——
conds = {
    2:  lambda d: d["gender"].eq(1),                                            # 男
    3:  lambda d: d["gender"].eq(0),                                            # 女
    4:  lambda d: d["marriage"].eq(1),                                          # marriage=1
    5:  lambda d: d["marriage"].eq(0),                                          # marriage=0
    6:  lambda d: d["kids15"].eq(1),                                            # kids15=1
    7:  lambda d: d["kids15"].eq(0),                                            # kids15=0
    8:  lambda d: d["age"] < 59,                                                # age<59
    9:  lambda d: d["age"].between(60, 79, inclusive="both"),                   # 60~79
    10: lambda d: d["age"] >= 80,                                               # 80+
    11: lambda d: d["district"].astype(str).str.lower().eq("east"),             # east
    12: lambda d: d["district"].astype(str).str.lower().eq("middle"),           # middle
    13: lambda d: d["district"].astype(str).str.lower().eq("west"),             # west
    14: lambda d: d["hsf15"] > 40,                                              # hsf15>40
    15: lambda d: d["hsf15"].between(25, 40, inclusive="both"),                 # 25~40
    16: lambda d: d["hsf15"] < 25,                                              # <25
    17: lambda d: d["ic15"] > 35000,                                            # ic15>35000
    18: lambda d: d["ic15"].between(5000, 35000, inclusive="both"),             # 5000~35000
    19: lambda d: d["ic15"] < 5000,                                             # <5000
    20: lambda d: d["educationrevised"].isin([6,7,8,9,10,11]),                  # 教育 6-11
    21: lambda d: d["educationrevised"].eq(5),                                  # 教育 5
    22: lambda d: d["educationrevised"].isin([1,2,3,4]),                        # 教育 1-4
}

def _to_num(s):
    return pd.to_numeric(s, errors="coerce")

def _safe_cov(x, y):
    z = pd.concat([x, y], axis=1).replace([np.inf, -np.inf], np.nan).dropna()
    if len(z) >= 2:
        return float(np.cov(z.iloc[:,0], z.iloc[:,1], ddof=1)[0,1])
    return 0.0

def compute_gamma_inv1(sub: pd.DataFrame) -> float:
    """
    本方法(对应 gamma3?2):
      Ec0 = E[1/c0],Ec1 = E[1/c1]
      cov0 = Cov( (1/c0)/Ec0 , (r0-r1)*m0 + p15 - p18 )
      cov1 = Cov( (1/c1)/Ec1 , (r0-r1)*m1 + p15 - p18 )
      γ_i = |p15-p18| + |0.5*(r0-r1)*(E[m0]+E[m1])| + 0.5*cov0 + 0.5*cov1
      返回子样本内 γ_i 的均值
    """
    if sub.empty:
        return float("nan")

    # 数值化
    for col in ["c0","c1","r0","r1","m0","m1","premium2015","premium2018"]:
        sub[col] = _to_num(sub[col])

    # 组内均值
    E_m0 = sub["m0"].mean()
    E_m1 = sub["m1"].mean()

    # 1/c,避免除以 0:把 0 当缺失
    c0_inv = 1.0 / sub["c0"].replace(0, np.nan)
    c1_inv = 1.0 / sub["c1"].replace(0, np.nan)
    Ec0 = c0_inv.replace([np.inf, -np.inf], np.nan).mean()
    Ec1 = c1_inv.replace([np.inf, -np.inf], np.nan).mean()

    y0 = (sub["r0"] - sub["r1"]) * sub["m0"] + (sub["premium2015"] - sub["premium2018"])
    y1 = (sub["r0"] - sub["r1"]) * sub["m1"] + (sub["premium2015"] - sub["premium2018"])

    cov0 = _safe_cov(c0_inv / Ec0, y0) if pd.notna(Ec0) and Ec0 != 0 else 0.0
    cov1 = _safe_cov(c1_inv / Ec1, y1) if pd.notna(Ec1) and Ec1 != 0 else 0.0

    gamma_series = (sub["premium2015"] - sub["premium2018"]).abs() \
                 + (0.5 * (sub["r0"] - sub["r1"]) * (E_m0 + E_m1)).abs() \
                 + 0.5 * cov0 + 0.5 * cov1

    return float(gamma_series.mean())

# —— 批量计算:gamma322 … gamma3222 ——
results = {}
for idx in range(2, 23):
    try:
        mask = conds[idx](data)
        sub = data.loc[mask].copy() if isinstance(mask, pd.Series) and len(mask)==len(data) else pd.DataFrame(columns=data.columns)
    except Exception:
        sub = pd.DataFrame(columns=data.columns)

    name = f"gamma3{idx}2"
    results[name] = compute_gamma_inv1(sub)
    globals()[name] = results[name]  # 可选:注册为同名变量

# 打印核对
for idx in range(2, 23):
    key = f"gamma3{idx}2"
    print(f"{key} = {results.get(key, np.nan)}")
gamma322 = 802.7906600812382
gamma332 = 881.1201345894027
gamma342 = 887.7108284615841
gamma352 = 576.663420801471
gamma362 = 846.9163570623545
gamma372 = 394.1618493492495
gamma382 = 740.2572102706334
gamma392 = 878.2989375956844
gamma3102 = 771.6318089577574
gamma3112 = 832.6376734492181
gamma3122 = 954.152803417741
gamma3132 = 658.8869816345907
gamma3142 = 787.623935492869
gamma3152 = 966.6883145675897
gamma3162 = 695.2482563497338
gamma3172 = 749.2273524859135
gamma3182 = 614.4296042994745
gamma3192 = 934.3856349227033
gamma3202 = 810.1788592321084
gamma3212 = 923.318782424085
gamma3222 = 808.3482289017528

health-based:合并数据¶

In [13]:
dataa = pd.merge(c0m0, c1m1full,on="ID", how="inner")
dataa
Out[13]:
ID c0 m0 householdID communityID c1 m1 gender age marriage ... premium2018 r0 r1 r0adjust r1adjust policyintergration2015 policyintergration2018 district GDPgrowthrate urban_nbs
0 64033321002 112.216 60.0 640333210 640333 123.670 0.0 0.0 59.0 1.0 ... 180.0 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural
1 64033327002 1029.200 6000.0 640333270 640333 1054.764 21000.0 0.0 62.0 1.0 ... 180.0 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural
2 64033325001 1062.400 3000.0 640333250 640333 78.020 100.0 1.0 66.0 1.0 ... 180.0 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural
3 64033322001 592.620 2000.0 640333220 640333 859.050 17050.0 1.0 63.0 1.0 ... 180.0 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural
4 64033330002 2058.400 2000.0 640333300 640333 4025.500 2000.0 1.0 59.0 1.0 ... 180.0 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3882 89676104001 2315.700 840.0 896761040 896761 891.420 8000.0 1.0 61.0 1.0 ... 220.0 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural
3883 89676114002 1935.145 300.0 896761140 896761 49.800 0.0 0.0 56.0 0.0 ... 220.0 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural
3884 89676118001 2466.096 1000.0 896761180 896761 661.095 3000.0 0.0 73.0 0.0 ... 220.0 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural
3885 89676115001 10721.940 800.0 896761150 896761 11638.260 2000.0 1.0 55.0 1.0 ... 220.0 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural
3886 89676124001 268.422 500.0 896761240 896761 313.242 101.0 1.0 69.0 0.0 ... 220.0 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural

3887 rows × 26 columns

In [14]:
#计算dh/dm 15
import pandas as pd
import statsmodels.api as sm
e1 = pd.merge(c0m0,hsf15,on="ID",how="inner")
e1= e1[['m0','hsf15']].copy()
# 删除包含 NaN 或 inf 的行
e1= e1.replace([np.inf, -np.inf], np.nan).dropna()
# 删除包含 0 的行
e1 = e1[(e1['hsf15']!=0) & (e1['m0']!=0)]
# 自变量(X)和因变量(Y)
X = e1['m0']
Y = e1['hsf15']

# 在 X 中添加常数项,以便进行 OLS 回归
X = sm.add_constant(X)

# 拟合 OLS 回归模型
model = sm.OLS(Y, X).fit()

# 输出回归结果
print(model.summary())

# 提取回归系数
coefficients = model.params

# 保存特定自变量的回归系数
h_m15 = coefficients['m0'] 
h_m15
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                  hsf15   R-squared:                       0.000
Model:                            OLS   Adj. R-squared:                  0.000
Method:                 Least Squares   F-statistic:                     1.297
Date:                Mon, 13 Oct 2025   Prob (F-statistic):              0.255
Time:                        01:34:37   Log-Likelihood:                -11963.
No. Observations:                3113   AIC:                         2.393e+04
Df Residuals:                    3111   BIC:                         2.394e+04
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
const         33.6007      0.216    155.587      0.000      33.177      34.024
m0         -1.706e-05    1.5e-05     -1.139      0.255   -4.64e-05    1.23e-05
==============================================================================
Omnibus:                       41.096   Durbin-Watson:                   1.849
Prob(Omnibus):                  0.000   Jarque-Bera (JB):               32.348
Skew:                          -0.167   Prob(JB):                     9.46e-08
Kurtosis:                       2.629   Cond. No.                     1.54e+04
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.54e+04. This might indicate that there are
strong multicollinearity or other numerical problems.
Out[14]:
np.float64(-1.7062284276591698e-05)
In [15]:
#计算dh/dm 18
import pandas as pd
import statsmodels.api as sm
f1 = pd.merge(c1m1,hsf18,on="ID",how="inner")
f1= f1[['m1','hsf18']].copy()
# 删除包含 NaN 或 inf 的行
f1= f1.replace([np.inf, -np.inf], np.nan).dropna()
# 删除包含 0 的行
f1 = f1[(f1['hsf18']!=0) & (f1['m1']!=0)]
# 自变量(X)和因变量(Y)
X = f1['m1']
Y = f1['hsf18']

# 在 X 中添加常数项,以便进行 OLS 回归
X = sm.add_constant(X)

# 拟合 OLS 回归模型
model = sm.OLS(Y, X).fit()

# 输出回归结果
print(model.summary())

# 提取回归系数
coefficients = model.params

# 保存特定自变量的回归系数
h_m18 = coefficients['m1'] 
h_m18
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                  hsf18   R-squared:                       0.000
Model:                            OLS   Adj. R-squared:                  0.000
Method:                 Least Squares   F-statistic:                     1.579
Date:                Mon, 13 Oct 2025   Prob (F-statistic):              0.209
Time:                        01:34:37   Log-Likelihood:                -26371.
No. Observations:                5630   AIC:                         5.275e+04
Df Residuals:                    5628   BIC:                         5.276e+04
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
const         51.5258      0.359    143.352      0.000      50.821      52.230
m1         -1.359e-05   1.08e-05     -1.257      0.209   -3.48e-05    7.61e-06
==============================================================================
Omnibus:                    14923.644   Durbin-Watson:                   1.748
Prob(Omnibus):                  0.000   Jarque-Bera (JB):              441.401
Skew:                          -0.235   Prob(JB):                     1.42e-96
Kurtosis:                       1.711   Cond. No.                     3.42e+04
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 3.42e+04. This might indicate that there are
strong multicollinearity or other numerical problems.
Out[15]:
np.float64(-1.3590936773055398e-05)
In [20]:
#最优化方法——健康计算 
import pandas as pd
import numpy as np

# 计算 E(m0) 和 E(m1)
E_m0 = dataa['m0'].mean()
E_m1 = dataa['m1'].mean()

# 计算 E(1/c0) 和 E(1/c1)
E_c0_inv2 = (1/dataa['c0']).mean()
E_c1_inv2 = (1/dataa['c1']).mean()

# 计算协方差
cov_c0_inv2 = np.cov((0.019743 * h_m15)/ (E_c0_inv2 * dataa['r0']), (dataa['r0'] - dataa['r1']) * dataa['m0'] + dataa['premium2015'] - dataa['premium2018'])[0, 1]
cov_c1_inv2 = np.cov((0.019743 * h_m18)/ (E_c1_inv2 * dataa['r1']), (dataa['r0'] - dataa['r1']) * dataa['m1'] + dataa['premium2015'] - dataa['premium2018'])[0, 1]

# 计算 gamma
dataa['gamma313'] = abs(dataa['premium2015'] - dataa['premium2018']) + abs(0.5 * (dataa['r0'] - dataa['r1']) * (E_m0 + E_m1)) + 0.5 * cov_c0_inv2 + 0.5 * cov_c1_inv2
gamma313 = dataa['gamma313'].mean()
print(gamma313)
dataa
665.7478215297924
Out[20]:
ID c0 m0 householdID communityID c1 m1 gender age marriage ... r0 r1 r0adjust r1adjust policyintergration2015 policyintergration2018 district GDPgrowthrate urban_nbs gamma313
0 64033321002 112.216 60.0 640333210 640333 123.670 0.0 0.0 59.0 1.0 ... 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural 476.535797
1 64033327002 1029.200 6000.0 640333270 640333 1054.764 21000.0 0.0 62.0 1.0 ... 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural 476.535797
2 64033325001 1062.400 3000.0 640333250 640333 78.020 100.0 1.0 66.0 1.0 ... 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural 476.535797
3 64033322001 592.620 2000.0 640333220 640333 859.050 17050.0 1.0 63.0 1.0 ... 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural 476.535797
4 64033330002 2058.400 2000.0 640333300 640333 4025.500 2000.0 1.0 59.0 1.0 ... 0.6167 0.700 0.544192 0.660903 0.0 1.0 east 0.118005 Rural 476.535797
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3882 89676104001 2315.700 840.0 896761040 896761 891.420 8000.0 1.0 61.0 1.0 ... 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural 525.032360
3883 89676114002 1935.145 300.0 896761140 896761 49.800 0.0 0.0 56.0 0.0 ... 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural 525.032360
3884 89676118001 2466.096 1000.0 896761180 896761 661.095 3000.0 0.0 73.0 0.0 ... 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural 525.032360
3885 89676115001 10721.940 800.0 896761150 896761 11638.260 2000.0 1.0 55.0 1.0 ... 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural 525.032360
3886 89676124001 268.422 500.0 896761240 896761 313.242 101.0 1.0 69.0 0.0 ... 0.6500 0.725 0.624462 0.685108 0.0 1.0 west 0.284050 Rural 525.032360

3887 rows × 27 columns

In [18]:
#健康based异质性—男性
dataamale = dataa.loc[dataa['gender'] == 1].copy()
import pandas as pd
import numpy as np

# 计算 E(m0) 和 E(m1)
E_m0 = dataamale['m0'].mean()
E_m1 = dataamale['m1'].mean()

E_c0_inv2 = (1/dataamale['c0']).mean()
E_c1_inv2 = (1/dataamale['c1']).mean()

# 计算协方差
cov_c0_inv2 = np.cov((0.019743 * h_m15)/ (E_c0_inv2 * dataamale['r0']), (dataamale['r0'] - dataamale['r1']) * dataamale['m0'] + dataamale['premium2015'] - dataamale['premium2018'])[0, 1]
cov_c1_inv2 = np.cov((0.019743 * h_m18)/ (E_c1_inv2 * dataamale['r1']), (dataamale['r0'] - dataamale['r1']) * dataamale['m1'] + dataamale['premium2015'] - dataamale['premium2018'])[0, 1]

# 计算 gamma
dataamale['gamma323'] = abs(dataamale['premium2015'] - dataamale['premium2018']) + abs(0.5 * (dataamale['r0'] - dataamale['r1']) * (E_m0 + E_m1)) + 0.5 * cov_c0_inv2 + 0.5 * cov_c1_inv2
gamma323 = dataamale['gamma323'].mean()
print(gamma323)
675.5628844320822
In [21]:
#健康based异质性—女性
dataafemale = dataa.loc[dataa['gender'] == 0].copy()
import pandas as pd
import numpy as np

# 计算 E(m0) 和 E(m1)
E_m0 = dataafemale['m0'].mean()
E_m1 = dataafemale['m1'].mean()

E_c0_inv2 = (1/dataafemale['c0']).mean()
E_c1_inv2 = (1/dataafemale['c1']).mean()

# 计算协方差
cov_c0_inv2 = np.cov((0.019743 * h_m15)/ (E_c0_inv2 * dataafemale['r0']), (dataafemale['r0'] - dataafemale['r1']) * dataafemale['m0'] + dataafemale['premium2015'] - dataafemale['premium2018'])[0, 1]
cov_c1_inv2 = np.cov((0.019743 * h_m18)/ (E_c1_inv2 * dataafemale['r1']), (dataafemale['r0'] - dataafemale['r1']) * dataafemale['m1'] + dataafemale['premium2015'] - dataafemale['premium2018'])[0, 1]

# 计算 gamma
dataafemale['gamma333'] = abs(dataafemale['premium2015'] - dataafemale['premium2018']) + abs(0.5 * (dataafemale['r0'] - dataafemale['r1']) * (E_m0 + E_m1)) + 0.5 * cov_c0_inv2 + 0.5 * cov_c1_inv2
gamma333 = dataafemale['gamma333'].mean()
print(gamma333)
653.9915283097725
In [19]:
import numpy as np
import pandas as pd

PHI = 0.019743  # 0.019743 常数

# —— 异质性条件——
conds = {
    2:  lambda d: d["gender"].eq(1),                                            # 男
    3:  lambda d: d["gender"].eq(0),                                            # 女
    4:  lambda d: d["marriage"].eq(1),                                          # marriage=1
    5:  lambda d: d["marriage"].eq(0),                                          # marriage=0
    6:  lambda d: d["kids15"].eq(1),                                            # kids15=1
    7:  lambda d: d["kids15"].eq(0),                                            # kids15=0
    8:  lambda d: d["age"] < 59,                                                # age<59
    9:  lambda d: d["age"].between(60, 79, inclusive="both"),                   # 60~79
    10: lambda d: d["age"] >= 80,                                               # 80+
    11: lambda d: d["district"].astype(str).str.lower().eq("east"),             # east
    12: lambda d: d["district"].astype(str).str.lower().eq("middle"),           # middle
    13: lambda d: d["district"].astype(str).str.lower().eq("west"),             # west
    14: lambda d: d["hsf15"] > 40,                                              # hsf15>40
    15: lambda d: d["hsf15"].between(25, 40, inclusive="both"),                 # 25~40
    16: lambda d: d["hsf15"] < 25,                                              # <25
    17: lambda d: d["ic15"] > 35000,                                            # ic15>35000
    18: lambda d: d["ic15"].between(5000, 35000, inclusive="both"),             # 5000~35000
    19: lambda d: d["ic15"] < 5000,                                             # <5000
    20: lambda d: d["educationrevised"].isin([6,7,8,9,10,11]),                  # 教育 6-11
    21: lambda d: d["educationrevised"].eq(5),                                  # 教育 5
    22: lambda d: d["educationrevised"].isin([1,2,3,4]),                        # 教育 1-4
}

def _to_num(s):
    return pd.to_numeric(s, errors="coerce")

def _safe_cov(x, y):
    """丢弃 NaN/Inf 后算样本协方差(与你 np.cov 默认口径一致)"""
    z = pd.concat([x, y], axis=1).replace([np.inf, -np.inf], np.nan).dropna()
    if len(z) >= 2:
        return float(np.cov(z.iloc[:,0], z.iloc[:,1])[0,1])
    return 0.0

def _align_health_for_subset(dataa_full: pd.DataFrame, data_sub: pd.DataFrame, h_full, id_col="ID"):
    """
    将 h_m15 / h_m18 与子样本按 index 或 ID 对齐;h_full 可为 Series 或 array-like。
    """
    if isinstance(h_full, pd.Series):
        # 与 dataa_full 同 index
        if h_full.index.equals(dataa_full.index):
            return h_full.loc[data_sub.index]
        # 若 h_full 的索引可能是 ID
        if id_col in data_sub.columns and h_full.index.isin(data_sub[id_col]).any():
            s = h_full.reindex(data_sub[id_col])
            s.index = data_sub.index
            return s
        # 兜底按 index 选
        try:
            return h_full.loc[data_sub.index]
        except Exception:
            return pd.Series(np.nan, index=data_sub.index)
    # array-like:包成与 dataa_full 对齐的 Series 再切
    try:
        base = pd.Series(h_full, index=dataa_full.index)
        return base.loc[data_sub.index]
    except Exception:
        return pd.Series(np.nan, index=data_sub.index)

def compute_gamma_health_inv1(dataa_full: pd.DataFrame, data_sub: pd.DataFrame, h_m15, h_m18) -> float:
    """
    本方法(对应 gamma3?3):
      Ec0 = E[1/c0],Ec1 = E[1/c1]
      cov0 = Cov( (PHI*h15)/(Ec0*r0) , (r0-r1)*m0 + p15 - p18 )
      cov1 = Cov( (PHI*h18)/(Ec1*r1) , (r0-r1)*m1 + p15 - p18 )
      γ_i  = |p15-p18| + |0.5*(r0-r1)*(E[m0]+E[m1])| + 0.5*cov0 + 0.5*cov1
      返回子样本内 γ_i 的均值
    """
    if data_sub.empty:
        return float("nan")

    # 数值化
    for col in ["c0","c1","r0","r1","m0","m1","premium2015","premium2018","ID"]:
        if col in data_sub.columns:
            data_sub[col] = _to_num(data_sub[col])

    # E[m0], E[m1]
    E_m0 = data_sub["m0"].mean()
    E_m1 = data_sub["m1"].mean()

    # E[1/c](把无穷替换为 NaN 再求均值,避免 1/0 影响)
    c0_inv = 1.0 / data_sub["c0"]
    c1_inv = 1.0 / data_sub["c1"]
    Ec0 = c0_inv.replace([np.inf, -np.inf], np.nan).mean()
    Ec1 = c1_inv.replace([np.inf, -np.inf], np.nan).mean()

    # 对齐 h_m15/h_m18
    h15 = _align_health_for_subset(dataa_full, data_sub, h_m15)
    h18 = _align_health_for_subset(dataa_full, data_sub, h_m18)

    # y0,y1
    y0 = (data_sub["r0"] - data_sub["r1"]) * data_sub["m0"] + (data_sub["premium2015"] - data_sub["premium2018"])
    y1 = (data_sub["r0"] - data_sub["r1"]) * data_sub["m1"] + (data_sub["premium2015"] - data_sub["premium2018"])

    # 两个协方差
    r0 = data_sub["r0"]
    r1 = data_sub["r1"]
    cov0 = _safe_cov((PHI * h15) / (Ec0 * r0), y0) if pd.notna(Ec0) and Ec0 != 0 else 0.0
    cov1 = _safe_cov((PHI * h18) / (Ec1 * r1), y1) if pd.notna(Ec1) and Ec1 != 0 else 0.0

    gamma_series = (data_sub["premium2015"] - data_sub["premium2018"]).abs() \
                 + (0.5 * (data_sub["r0"] - data_sub["r1"]) * (E_m0 + E_m1)).abs() \
                 + 0.5 * cov0 + 0.5 * cov1

    return float(gamma_series.mean())

# —— 批量计算:gamma323 … gamma3223 ——
results = {}
for idx in range(2, 23):
    try:
        mask = conds[idx](dataa)
        sub = dataa.loc[mask].copy() if isinstance(mask, pd.Series) and len(mask)==len(dataa) else pd.DataFrame(columns=dataa.columns)
    except Exception:
        sub = pd.DataFrame(columns=dataa.columns)

    name = f"gamma3{idx}3"
    results[name] = compute_gamma_health_inv1(dataa_full=dataa, data_sub=sub, h_m15=h_m15, h_m18=h_m18)
    globals()[name] = results[name]  # 可选:注册为同名变量

# 打印核对
for idx in range(2, 23):
    key = f"gamma3{idx}3"
    print(f"{key} = {results.get(key, np.nan)}")
gamma323 = 675.5628844320822
gamma333 = 653.9915283097725
gamma343 = 711.7527340731003
gamma353 = 478.53226004335176
gamma363 = 669.9089945050528
gamma373 = 364.73161872871424
gamma383 = 646.919021748351
gamma393 = 679.7402110445717
gamma3103 = 539.7100207150593
gamma3113 = 594.8823272349582
gamma3123 = 741.652210399491
gamma3133 = 584.1947275016881
gamma3143 = 616.7061952195254
gamma3153 = 763.3067968734329
gamma3163 = 560.3194837995072
gamma3173 = 589.0182650573405
gamma3183 = 540.942205343509
gamma3193 = 715.2644872566253
gamma3203 = 650.674324132809
gamma3213 = 748.8317568381137
gamma3223 = 637.7790899630422

用完全信息法求解¶

In [24]:
d1 = pd.merge(c0m0, c1m1, on="ID", how="inner")
d2 = pd.merge(d1, hsf15, on="ID", how="inner")
d3 = pd.merge(d2, hsf18, on="ID", how="inner")
d3
Out[24]:
ID c0 m0 c1 m1 hsf15 hsf18
0 64033321002 112.216 60.0 123.670 0.0 54.436016 10.551840
1 64033327002 1029.200 6000.0 1054.764 21000.0 28.096293 39.754467
2 64033322001 592.620 2000.0 859.050 17050.0 21.303569 59.803845
3 64033330002 2058.400 2000.0 4025.500 2000.0 34.523055 68.626626
4 64033341001 5436.500 500.0 1806.578 2500.0 50.384267 78.657775
... ... ... ... ... ... ... ...
3750 89676104001 2315.700 840.0 891.420 8000.0 27.522919 42.058152
3751 89676114002 1935.145 300.0 49.800 0.0 35.235805 15.917436
3752 89676118001 2466.096 1000.0 661.095 3000.0 32.251424 54.653869
3753 89676115001 10721.940 800.0 11638.260 2000.0 32.757347 73.821948
3754 89676124001 268.422 500.0 313.242 101.0 34.706036 95.825352

3755 rows × 7 columns

In [33]:
import numpy as np
import pandas as pd
# 参数
PHI = 0.019743
d3["gamma311"] = d3["c1"] * (PHI * (d3["hsf18"] - d3["hsf15"]) - np.log(d3["c0"] / d3["c1"]))

gamma311= d3["gamma311"].mean()
print(gamma311)
d3
2069.455364572046
Out[33]:
ID c0 m0 c1 m1 hsf15 hsf18 gamma311
0 64033321002 112.216 60.0 123.670 0.0 54.436016 10.551840 -95.128712
1 64033327002 1029.200 6000.0 1054.764 21000.0 28.096293 39.754467 268.651118
2 64033322001 592.620 2000.0 859.050 17050.0 21.303569 59.803845 971.916021
3 64033330002 2058.400 2000.0 4025.500 2000.0 34.523055 68.626626 5410.380456
4 64033341001 5436.500 500.0 1806.578 2500.0 50.384267 78.657775 -981.870016
... ... ... ... ... ... ... ... ...
3750 89676104001 2315.700 840.0 891.420 8000.0 27.522919 42.058152 -595.185530
3751 89676114002 1935.145 300.0 49.800 0.0 35.235805 15.917436 -201.257990
3752 89676118001 2466.096 1000.0 661.095 3000.0 32.251424 54.653869 -577.930962
3753 89676115001 10721.940 800.0 11638.260 2000.0 32.757347 73.821948 10389.989777
3754 89676124001 268.422 500.0 313.242 101.0 34.706036 95.825352 426.351916

3755 rows × 8 columns

In [29]:
#异质性计算男性
import numpy as np
import pandas as pd
# 参数
PHI = 0.019743

d4 = pd.merge(d1, hsf18full, on="ID", how="inner")
dmale = d4.loc[d4['gender'] == 1].copy()

dmale["gamma321"] = dmale["c1"] * (PHI * (dmale["hsf18"] - dmale["hsf15"]) - np.log(dmale["c0"] / dmale["c1"]))

gamma321= dmale["gamma321"].mean()
print(gamma321)
1972.9361597607306
In [30]:
#异质性计算女性
import numpy as np
import pandas as pd
# 参数
PHI = 0.019743

d4 = pd.merge(d1, hsf18full, on="ID", how="inner")
dfemale = d4.loc[d4['gender'] == 0].copy()

dfemale["gamma331"] = dfemale["c1"] * (PHI * (dfemale["hsf18"] - dfemale["hsf15"]) - np.log(dfemale["c0"] / dfemale["c1"]))

gamma331= dfemale["gamma331"].mean()
print(gamma331)
2172.511938431705
In [31]:
import numpy as np
import pandas as pd

# 固定合并
d4 = pd.merge(d1, hsf18full, on="ID", how="inner")

PHI = 0.019743

# —— 异质性条件——
conds = {
    2:  lambda d: d["gender"].eq(1),                                            # 男
    3:  lambda d: d["gender"].eq(0),                                            # 女
    4:  lambda d: d["marriage"].eq(1),                                          # marriage=1
    5:  lambda d: d["marriage"].eq(0),                                          # marriage=0
    6:  lambda d: d["kids15"].eq(1),                                            # kids15=1
    7:  lambda d: d["kids15"].eq(0),                                            # kids15=0
    8:  lambda d: d["age"] < 59,                                                # age<59
    9:  lambda d: d["age"].between(60, 79, inclusive="both"),                   # 60~79
    10: lambda d: d["age"] >= 80,                                               # 80+
    11: lambda d: d["district"].astype(str).str.lower().eq("east"),             # east
    12: lambda d: d["district"].astype(str).str.lower().eq("middle"),           # middle
    13: lambda d: d["district"].astype(str).str.lower().eq("west"),             # west
    14: lambda d: d["hsf15"] > 40,                                              # hsf15>40
    15: lambda d: d["hsf15"].between(25, 40, inclusive="both"),                 # 25~40
    16: lambda d: d["hsf15"] < 25,                                              # <25
    17: lambda d: d["ic15"] > 35000,                                            # ic15>35000
    18: lambda d: d["ic15"].between(5000, 35000, inclusive="both"),             # 5000~35000
    19: lambda d: d["ic15"] < 5000,                                             # <5000
    20: lambda d: d["educationrevised"].isin([6,7,8,9,10,11]),                  # 教育 6-11
    21: lambda d: d["educationrevised"].eq(5),                                  # 教育 5
    22: lambda d: d["educationrevised"].isin([1,2,3,4]),                        # 教育 1-4
}

def compute_gamma(sub: pd.DataFrame) -> float:
    """
    γ_i = c1 * ( PHI*(hsf18 - hsf15) - ln(c0/c1) )
    返回子样本内 γ_i 的均值
    """
    if sub.empty:
        return float("nan")
    # 若需要更稳健可数值化;为尽量贴近你原始结果,这里不强制转型
    gamma_series = sub["c1"] * (PHI * (sub["hsf18"] - sub["hsf15"]) - np.log(sub["c0"] / sub["c1"]))
    return float(gamma_series.mean())

# —— 批量计算:gamma321 … gamma3221 ——
results = {}
for idx in range(2, 23):
    try:
        mask = conds[idx](d4)
        sub = d4.loc[mask].copy() if isinstance(mask, pd.Series) and len(mask)==len(d4) else pd.DataFrame(columns=d4.columns)
    except Exception:
        sub = pd.DataFrame(columns=d4.columns)

    name = f"gamma3{idx}1"
    results[name] = compute_gamma(sub)
    globals()[name] = results[name]  # 可选:注册为同名变量,便于后续直接用

# 打印核对
for idx in range(2, 23):
    key = f"gamma3{idx}1"
    print(f"{key} = {results.get(key, np.nan)}")
gamma321 = 1972.9361597607306
gamma331 = 2172.511938431705
gamma341 = 2133.875674113165
gamma351 = 1810.9140421680336
gamma361 = 2089.855534379301
gamma371 = 579.8554327323171
gamma381 = 2722.573800517208
gamma391 = 1519.6215845307818
gamma3101 = 816.5738606477122
gamma3111 = 2828.1348185073775
gamma3121 = 2138.774183188456
gamma3131 = 1400.2565528289158
gamma3141 = 2362.867406843136
gamma3151 = 2091.3356304820554
gamma3161 = 1631.1663360643925
gamma3171 = 2620.5894489874076
gamma3181 = 2070.3434949871958
gamma3191 = 2016.9799313921617
gamma3201 = 3566.7253958692945
gamma3211 = 2454.8369532172455
gamma3221 = 1720.6506749898997
In [32]:
# -*- coding: utf-8 -*-
import pandas as pd

# 1) 行索引与数据
rows = [
    "全样本",
    "男性","女性",
    "有配偶","无配偶",
    "有子女","无子女",
    "小于59 岁","60 岁—79 岁","80 岁及以上",
    "东部","中部","西部",
    "健康状况较好","健康状况中等","健康状况较差",
    "较高收入","中等收入","较低收入",
    "教育程度较高","教育程度中等","教育程度较低",
]

data = [
[gamma311, gamma312, gamma313],
[gamma321, gamma322, gamma323],
[gamma331, gamma332, gamma333],
[gamma341, gamma342, gamma343],
[gamma351, gamma352, gamma353],
[gamma361, gamma362, gamma363],
[gamma371, gamma372, gamma373],
[gamma381, gamma382, gamma383],
[gamma391, gamma392, gamma393],
[gamma3101, gamma3102, gamma3103],
[gamma3111, gamma3112, gamma3113],
[gamma3121, gamma3122, gamma3123],
[gamma3131, gamma3132, gamma3133],
[gamma3141, gamma3142, gamma3143],
[gamma3151, gamma3152, gamma3153],
[gamma3161, gamma3162, gamma3163],
[gamma3171, gamma3172, gamma3173],
[gamma3181, gamma3182, gamma3183],
[gamma3191, gamma3192, gamma3193],
[gamma3201, gamma3202, gamma3203],
[gamma3211, gamma3212, gamma3213],
[gamma3221, gamma3222, gamma3223],
]

# 2) 多级列索引
cols = pd.MultiIndex.from_tuples([
    ("完全信息方法",""),
    ("最优化方法","仅假设效用函数\n的消费部分"),
    ("最优化方法","仅假设效用函数\n的健康部分"),
])

df = pd.DataFrame(data, index=rows, columns=cols)

# 3) 分组起始行(加粗横线)
group_starts = {
    "男性",           # 性别组
    "有配偶",         # 婚姻组
    "有子女",         # 子女组
    "45 岁—59 岁",    # 年龄组
    "东部",           # 地区组
    "健康状况较好",   # 健康组
    "较高收入",       # 收入组
    "教育程度较高"    # 教育组
}

def row_borders(row):
    label = row.name
    if label in group_starts:
        return ['border-top: 2px solid #4a4a4a'] * len(row)
    return [''] * len(row)

# 4) 样式与展示
styler = (
    df.style
      .set_table_styles([
          {'selector': 'th.col_heading.level0',
           'props': [('font-weight', '700'),
                     ('border-bottom','1px solid #4a4a4a')]},
          {'selector': 'th.col_heading.level1',
           'props': [('font-weight', '700')]},
          {'selector': 'th.row_heading',
           'props': [('font-weight', '700')]},
          {'selector': 'table',
           'props': [('border-collapse','collapse'),
                     ('font-family','-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,PingFang SC,Helvetica,Arial')]}
      ])
      .format(precision=0)
      .set_properties(**{
          'text-align': 'center',
          'padding': '6px',
          'border':'1px solid #a0a0a0'
      })
      .apply(row_borders, axis=1)
)

# 在 Jupyter 中显示
styler
Out[32]:
  完全信息方法 最优化方法
  仅假设效用函数 的消费部分 仅假设效用函数 的健康部分
全样本 2069 842 666
男性 1973 803 676
女性 2173 881 654
有配偶 2134 888 712
无配偶 1811 577 479
有子女 2090 847 670
无子女 580 394 365
小于59 岁 2723 740 647
60 岁—79 岁 1520 878 680
80 岁及以上 817 772 540
东部 2828 833 595
中部 2139 954 742
西部 1400 659 584
健康状况较好 2363 788 617
健康状况中等 2091 967 763
健康状况较差 1631 695 560
较高收入 2621 749 589
中等收入 2070 614 541
较低收入 2017 934 715
教育程度较高 3567 810 651
教育程度中等 2455 923 749
教育程度较低 1721 808 638