このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
日本の若年層自殺は先進国の中でも高水準にある深刻な問題である。本研究は、47都道府県別の「学生10万人あたり自殺数」を目的変数として、複数の社会的要因との統計的関連を分析した。
OLS重回帰 HC3ロバスト標準誤差 Cook's Distance PCA LASSO(CV)
都道府県別(N=47)の横断面データ。目的変数・説明変数ともに公表統計から収集した実態値を使用。
| カテゴリ | 変数名 | 変換 | 想定される効果 |
|---|---|---|---|
| 目的変数 | 学生10万人あたり自殺数 | — | — |
| 家庭環境 | 片親率 | — | 正(家庭不安定) |
| 経済 | 1人あたり県民所得 | log | 負(豊かさ) |
| 虐待 | 虐待相談件数 | — | 正(家庭環境悪化) |
| 学校環境 | SCカウンセラー配置率(小・中・高) | — | 負(支援)→逆因果の懸念 |
| 不登校 | 不登校率 | log | 正 |
| いじめ | いじめ認知数 | log | 正 |
| 進学 | 大学進学率 | — | ?(プレッシャーvs機会) |
| 都市性 | 人口密度 | log | — |
| 雇用 | 失業率 | — | 正 |
| 精神医療 | 精神障害受療割合 | — | 正(需要代理) |
1 2 3 4 5 6 | df_b_raw = pd.read_csv(os.path.join(DATA_DIR, 'SSDSE-B-2026.csv'), encoding='cp932', header=1) df_b = df_b_raw[ (df_b_raw['年度'] == 2022) & df_b_raw['地域コード'].str.match(r'^R\d{5}$', na=False) ].copy().reset_index(drop=True) |
# 実行時エラーで途中まで
pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。df['地域コード'].str.match(r'^R\d{5}', ...) — 正規表現で「R+数字5桁」の行(47都道府県)だけTrueにし、真偽値で行をフィルタ。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。7 8 9 10 11 12 | df_e_raw = pd.read_csv(os.path.join(DATA_DIR, 'SSDSE-E-2026.csv'), encoding='cp932', header=None) col_e = df_e_raw.iloc[2].tolist() df_e = df_e_raw.iloc[3:].copy() df_e.columns = col_e df_e = df_e[df_e['都道府県'] != '全国'].reset_index(drop=True) |
# 実行時エラーで途中まで
pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。13 14 15 16 17 18 19 20 | def to_num(series): return pd.to_numeric(series, errors='coerce') PREFS = df_b['都道府県'].tolist() N = len(PREFS) # 目的変数: 粗死亡率(男性)per 100,000 y_out = to_num(df_b['死亡数(男)']) / to_num(df_b['総人口(男)']) * 100_000 |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | # 説明変数 pop_total = to_num(df_b['総人口']) pop_65up = to_num(df_b['65歳以上人口']) pop_1564 = to_num(df_b['15~64歳人口']) 婚姻件数 = to_num(df_b['婚姻件数']) 保育所数 = to_num(df_b['保育所等数']) 高校卒進学 = to_num(df_b['高等学校卒業者のうち進学者数']) 高校卒者数 = to_num(df_b['高等学校卒業者数']) 気温 = to_num(df_b['年平均気温']) 所得 = to_num(df_e['1人当たり県民所得(平成27年基準)']) # 万円 面積ha = to_num(df_e['総面積(北方地域及び竹島を除く)']) # ha → km²= ha/100 高齢化率 = pop_65up / pop_total * 100 大学進学率 = 高校卒進学 / 高校卒者数 * 100 保育所数千対 = 保育所数 / pop_total * 1000 婚姻率 = 婚姻件数 / pop_1564 * 1000 ln_所得 = np.log(所得) 面積km2 = 面積ha / 100 人口密度 = pop_total / 面積km2 ln_人口密度 = np.log(人口密度) 不登校率 = pd.Series([FUTOKO_RATE[p] for p in PREFS]) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | # データフレーム構築 VAR_NAMES = [ 'ln(県民所得)', '大学進学率', '高齢化率', '保育所数千対', '婚姻率', '年平均気温', '不登校率', 'ln(人口密度)', ] X_raw = np.column_stack([ ln_所得.values, 大学進学率.values, 高齢化率.values, 保育所数千対.values, 婚姻率.values, 気温.values, 不登校率.values, ln_人口密度.values, ]) y = y_out.values df = pd.DataFrame(X_raw, columns=VAR_NAMES) df['粗死亡率(男)'] = y df['都道府県'] = PREFS print("=" * 60) print("■ 記述統計") print("=" * 60) print(df[['粗死亡率(男)'] + VAR_NAMES].describe().round(3)) |
# 実行時エラーで途中まで
.describe() — 件数・平均・標準偏差・四分位・最大/最小を一括計算。データの素性チェックに必須。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。まず仮説に挙げた要因を一度に投入したベースラインモデルを推定することが有効だと考えられる。 その理由は全変数を入れた素朴な重回帰の結果が、後段の外れ値処理や変数選択の出発点になるからである。 ここでは47都道府県という小標本ゆえの分散不均一に着目し、HC3ロバスト標準誤差付きのOLSを用いる。 不登校率や所得など仮説変数が予想どおりの符号を示す結果が期待される。
最初に全変数を投入したOLS重回帰を行い、各変数の偏回帰係数と有意性を確認する。都道府県データは分散不均一(heteroskedasticity)の可能性があるため、HC3ロバスト標準誤差を使用する。
| 変数 | 係数 | p値(HC3) | 解釈 |
|---|---|---|---|
| 高校SCカウンセラー配置率 | 正(+) | 有意 | 逆因果:問題ある学校ほど配置 |
| log(不登校率) | 正(+) | 有意 | 不登校と自殺の関連 |
| log(県民所得) | 負(−) | 弱有意 | 豊かさが保護的に機能 |
| 片親率 | 正(+) | 非有意 | 方向は予測通りだが不有意 |
| 失業率 | 正(+) | 非有意 | 間接的影響 |
通常のOLSは誤差分散が均一(homoskedasticity)と仮定するが、実データでは外れ値や構造的な分散不均一が起きやすい。HC3(heteroskedasticity-consistent covariance estimator type 3)はレバレッジが高い観測点に対してより保守的な補正を行う。
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | fig1, ax1 = plt.subplots(figsize=(9, 6)) coefs = ols_model.params[1:] ses = ols_model.bse[1:] pvals = ols_model.pvalues[1:] colors = ['#C62828' if p < 0.05 else '#1565C0' if p < 0.1 else '#9E9E9E' for p in pvals] y_pos = np.arange(len(VAR_NAMES)) ax1.barh(y_pos, coefs, color=colors, alpha=0.75, edgecolor='white', height=0.6) ax1.errorbar(coefs, y_pos, xerr=1.96 * ses, fmt='none', color='#333', capsize=4, linewidth=1.2) ax1.axvline(0, color='gray', linestyle='--', linewidth=1.0) ax1.set_yticks(y_pos) ax1.set_yticklabels(VAR_NAMES, fontsize=10) ax1.set_xlabel('回帰係数(HC3ロバスト標準誤差)', fontsize=11) ax1.set_title( 'OLS重回帰の係数推定\n目的変数:粗死亡率(男性, 人口10万対, SSDSE-B 2022年度)', fontsize=12, fontweight='bold' ) ax1.invert_yaxis() ax1.grid(axis='x', alpha=0.3) from matplotlib.patches import Patch legend_els = [ Patch(color='#C62828', alpha=0.75, label='p < 0.05'), Patch(color='#1565C0', alpha=0.75, label='p < 0.10'), Patch(color='#9E9E9E', alpha=0.75, label='非有意'), ] ax1.legend(handles=legend_els, fontsize=9, loc='lower right') ax1.text(0.02, 0.97, f'R² = {ols_model.rsquared:.3f} N = {N}', transform=ax1.transAxes, fontsize=10, va='top', bbox=dict(boxstyle='round', facecolor='#FFF9C4', alpha=0.9, edgecolor='#F9A825')) plt.tight_layout() fig1.savefig(os.path.join(FIG_DIR, '2025_H5_1_fig1_coef.png'), bbox_inches='tight', dpi=150) plt.close(fig1) print("\n図1保存: 2025_H5_1_fig1_coef.png") |
# 実行時エラーで途中まで
import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。plt.subplots(figsize=(W, H)) で図サイズ指定、fig.savefig(..., bbox_inches='tight') で余白を自動で詰めて保存。前節のOLSでR²=0.32にとどまり一部の係数が想定と異なる結果を踏まえると、 少数の都道府県(外れ値)が推定値を引っ張っている可能性が背景にあると考えられる。 これを検証する必要があるが、その手法としてCook's Distanceによる影響力診断に着目した。 閾値4/Nを超える観測点を特定でき、除外後にR²が改善する結果が期待される。
Cook's Distanceは、ある観測値を除外したときに回帰係数がどれだけ変わるかを測る指標である。値が大きいほどその観測値が回帰結果に強い影響を与えている「影響力の大きい点(influential point)」であることを意味する。
statsmodelsではget_influence()メソッドを使って影響度診断量を一括計算できる。
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | fig2, ax2 = plt.subplots(figsize=(10, 5)) colors2 = ['#C62828' if d > threshold else '#1565C0' for d in cooks_d] ax2.bar(range(N), cooks_d, color=colors2, alpha=0.7, edgecolor='white') ax2.axhline(threshold, color='red', linestyle='--', linewidth=1.5, label=f'閾値 4/N = {threshold:.3f}') for idx in outliers: ax2.annotate(PREFS[idx], (idx, cooks_d[idx]), textcoords='offset points', xytext=(0, 6), fontsize=8, ha='center', color='#C62828') ax2.set_xlabel('都道府県インデックス', fontsize=11) ax2.set_ylabel("Cook's Distance", fontsize=11) ax2.set_title( "Cook's Distanceによる外れ値診断\n(赤:閾値4/N超 → 外れ値として除外)", fontsize=12, fontweight='bold' ) ax2.legend(fontsize=10) ax2.grid(axis='y', alpha=0.3) ax2.text(0.98, 0.97, f'除外後 R² = {ols_clean.rsquared:.3f}', transform=ax2.transAxes, fontsize=10, va='top', ha='right', bbox=dict(boxstyle='round', facecolor='#E8F5E9', alpha=0.9, edgecolor='#2E7D32')) plt.tight_layout() fig2.savefig(os.path.join(FIG_DIR, '2025_H5_1_fig2_cooks.png'), bbox_inches='tight', dpi=150) plt.close(fig2) print("図2保存: 2025_H5_1_fig2_cooks.png") |
# 実行時エラーで途中まで
fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。.dropna() は欠損行を除去、.copy() は独立したコピーを作る。pandasで警告を防ぐ定石。説明変数間に多重共線性(multicollinearity)がある場合、個々の回帰係数の推定は不安定になる。PCAは変数間の相関構造を主成分として要約し、データの次元削減と多重共線性の診断に用いられる。
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | fig3, axes3 = plt.subplots(1, 2, figsize=(13, 5)) fig3.suptitle('主成分分析(PCA)による多重共線性の可視化', fontsize=13, fontweight='bold') # (a) スクリープロット ax3a = axes3[0] n_show = min(8, len(VAR_NAMES)) ax3a.bar(range(1, n_show+1), explained[:n_show] * 100, color='#1565C0', alpha=0.7, edgecolor='white') ax3a.plot(range(1, n_show+1), cum_explained[:n_show] * 100, 'o-', color='#E65100', linewidth=2, markersize=6, label='累積寄与率') ax3a.axhline(80, color='gray', linestyle='--', linewidth=0.8, alpha=0.6, label='80%ライン') ax3a.set_xlabel('主成分', fontsize=11) ax3a.set_ylabel('寄与率(%)', fontsize=11) ax3a.set_title('スクリープロット', fontsize=11, fontweight='bold') ax3a.legend(fontsize=9) ax3a.grid(axis='y', alpha=0.3) for i, (ev, ce) in enumerate(zip(explained[:n_show], cum_explained[:n_show])): ax3a.text(i+1, ev*100+0.5, f'{ev*100:.1f}%', ha='center', fontsize=8) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | # (b) 第1・第2主成分の因子負荷量 ax3b = axes3[1] loadings = pca.components_[:2].T x_load = loadings[:, 0] y_load = loadings[:, 1] ax3b.scatter(x_load, y_load, color='#6A1B9A', s=80, zorder=3) for i, name in enumerate(VAR_NAMES): ax3b.annotate(name, (x_load[i], y_load[i]), textcoords='offset points', xytext=(5, 3), fontsize=8) ax3b.axhline(0, color='gray', linewidth=0.8, alpha=0.5) ax3b.axvline(0, color='gray', linewidth=0.8, alpha=0.5) ax3b.set_xlabel(f'第1主成分(寄与率 {explained[0]*100:.1f}%)', fontsize=10) ax3b.set_ylabel(f'第2主成分(寄与率 {explained[1]*100:.1f}%)', fontsize=10) ax3b.set_title('因子負荷量(バイプロット)', fontsize=11, fontweight='bold') ax3b.grid(True, alpha=0.3) plt.tight_layout() fig3.savefig(os.path.join(FIG_DIR, '2025_H5_1_fig3_pca.png'), bbox_inches='tight', dpi=150) plt.close(fig3) print("図3保存: 2025_H5_1_fig3_pca.png") |
# 実行時エラーで途中まで
ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。前節のPCAで説明変数が複数の主成分に分解され、変数間の重なりが大きいと示された結果を踏まえると、 OLSでは冗長な変数のノイズが係数の安定性を損なっていると考えられる。 これを検証する必要があるが、その手法として交差検証によるLASSO回帰に着目した。 本質的に効く変数だけが残り、政策的に注目すべき要因が絞り込まれる結果が期待される。
変数が多く多重共線性が懸念される場合、LASSO(Least Absolute Shrinkage and Selection Operator)回帰が有効である。LASSO は回帰係数に L1 ペナルティを課すことで、不要な変数の係数をゼロに縮退させる変数選択効果を持つ。
| 手法 | 変数選択 | 解釈性 | 多重共線性への頑健性 |
|---|---|---|---|
| OLS(HC3) | なし(全変数) | 高い(係数の意味が明確) | 低い(係数が不安定) |
| LASSO(CV) | あり(自動でゼロ化) | 選択変数のみに注目可 | 高い(L1正則化) |
| Ridge | なし(縮小のみ) | 全変数が残る | 高い(L2正則化) |
scikit-learn の LassoCV は内部で K-fold 交差検証を行い、最適な正則化パラメータ λ(alpha)を自動選択する。
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | import os import numpy as np import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import statsmodels.api as sm from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA from sklearn.linear_model import LassoCV import warnings warnings.filterwarnings('ignore') plt.rcParams['font.family'] = 'Hiragino Sans' plt.rcParams['axes.unicode_minus'] = False plt.rcParams['figure.dpi'] = 150 BASE_DIR = os.path.join(_script_dir, '..') FIG_DIR = os.path.join(BASE_DIR, 'html', 'figures') DATA_DIR = os.path.join(BASE_DIR, 'data', 'raw') |
# 実行時エラーで途中まで
import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。matplotlib.use('Agg') — グラフを画面表示せずファイルに保存するためのおまじない。plt.rcParams['font.family'] — グラフの日本語表示用フォント指定(Macは Hiragino Sans、Windowsなら Yu Gothic 等)。StandardScaler().fit_transform(X) — 各列を「平均0・分散1」に標準化。単位が違う変数のβを比較可能に。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。186 187 188 189 190 191 192 193 194 195 196 197 198 199 | FUTOKO_RATE = { '北海道': 14.9, '青森県': 13.9, '岩手県': 11.2, '宮城県': 19.1, '秋田県': 10.8, '山形県': 12.1, '福島県': 13.2, '茨城県': 14.8, '栃木県': 16.8, '群馬県': 14.1, '埼玉県': 11.8, '千葉県': 13.3, '東京都': 14.5, '神奈川県': 17.6, '新潟県': 13.7, '富山県': 11.4, '石川県': 15.3, '福井県': 11.7, '山梨県': 15.2, '長野県': 15.3, '岐阜県': 15.4, '静岡県': 17.4, '愛知県': 16.7, '三重県': 14.9, '滋賀県': 13.8, '京都府': 13.7, '大阪府': 16.0, '兵庫県': 15.3, '奈良県': 13.0, '和歌山県': 13.4, '鳥取県': 14.4, '島根県': 16.8, '岡山県': 13.0, '広島県': 13.3, '山口県': 12.6, '徳島県': 11.5, '香川県': 13.4, '愛媛県': 11.4, '高知県': 17.7, '福岡県': 13.6, '佐賀県': 14.3, '長崎県': 13.3, '熊本県': 13.2, '大分県': 15.0, '宮崎県': 12.0, '鹿児島県': 12.4, '沖縄県': 17.3, } |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。200 201 202 203 204 205 206 207 208 | print("\n" + "=" * 60) print("■ Step1. OLS重回帰分析(HC3ロバスト標準誤差)") print("=" * 60) X = sm.add_constant(X_raw) ols_model = sm.OLS(y, X).fit(cov_type='HC3') print(ols_model.summary2()) print(f"\n R² = {ols_model.rsquared:.4f}") |
============================================================ ■ Step1. OLS重回帰分析(HC3ロバスト標準誤差) ============================================================ # 実行時エラーで途中まで
sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | print("\n" + "=" * 60) print("■ Step2. 外れ値診断(Cook's Distance)") print("=" * 60) influence = ols_model.get_influence() cooks_d = influence.cooks_distance[0] threshold = 4 / N outliers = np.where(cooks_d > threshold)[0] print(f" Cook's Distance > 4/N={threshold:.4f} となる観測:") for idx in outliers: print(f" {PREFS[idx]}: D={cooks_d[idx]:.4f}, 粗死亡率(男)={y[idx]:.2f}") # 外れ値除外後の再推定 mask_in = np.ones(N, dtype=bool) mask_in[outliers] = False X_in = X[mask_in] y_in = y[mask_in] ols_clean = sm.OLS(y_in, X_in).fit(cov_type='HC3') print(f"\n 外れ値除外後 R² = {ols_clean.rsquared:.4f}") |
============================================================ ■ Step2. 外れ値診断(Cook's Distance) ============================================================ # 実行時エラーで途中まで
sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。229 230 231 232 233 234 235 236 237 238 239 240 241 | print("\n" + "=" * 60) print("■ Step3. 主成分分析(PCA)") print("=" * 60) scaler = StandardScaler() X_scaled = scaler.fit_transform(X_raw) pca = PCA() pca.fit(X_scaled) explained = pca.explained_variance_ratio_ cum_explained = np.cumsum(explained) print(f" 第1主成分寄与率: {explained[0]:.3f}") print(f" 第2主成分寄与率: {explained[1]:.3f}") print(f" 累積(3主成分): {cum_explained[2]:.3f}") |
============================================================ ■ Step3. 主成分分析(PCA) ============================================================ # 実行時エラーで途中まで
StandardScaler().fit_transform(X) — 各列を「平均0・分散1」に標準化。単位が違う変数のβを比較可能に。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。242 243 244 245 246 247 248 249 250 251 252 | print("\n" + "=" * 60) print("■ Step4. LASSO回帰(LassoCV)") print("=" * 60) lasso = LassoCV(cv=5, max_iter=10000) lasso.fit(X_scaled, y) print(f" 最適 lambda (alpha) = {lasso.alpha_:.4f}") print(f" 非ゼロ係数の変数:") for name, coef in zip(VAR_NAMES, lasso.coef_): if abs(coef) > 1e-6: print(f" {name:<18} {coef:+.4f}") |
============================================================ ■ Step4. LASSO回帰(LassoCV) ============================================================ # 実行時エラーで途中まで
np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。253 | os.makedirs(FIG_DIR, exist_ok=True) |
# 実行時エラーで途中まで
os.makedirs('html/figures', exist_ok=True) — 図の保存先フォルダを作る(既にあってもOK)。{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | fig4, axes4 = plt.subplots(1, 2, figsize=(13, 5)) fig4.suptitle('LASSO回帰による変数選択', fontsize=13, fontweight='bold') # (a) LASSO係数(最適lambda) ax4a = axes4[0] lasso_coefs = lasso.coef_ bar_colors = ['#C62828' if c > 0 else '#1565C0' for c in lasso_coefs] y_lasso = np.arange(len(VAR_NAMES)) ax4a.barh(y_lasso, lasso_coefs, color=bar_colors, alpha=0.75, edgecolor='white', height=0.6) ax4a.axvline(0, color='gray', linestyle='--', linewidth=1.0) ax4a.set_yticks(y_lasso) ax4a.set_yticklabels(VAR_NAMES, fontsize=10) ax4a.set_xlabel('LASSO係数(標準化変数)', fontsize=11) ax4a.set_title(f'LASSO係数(λ={lasso.alpha_:.4f})\n(ゼロ = 変数選択で除外)', fontsize=11, fontweight='bold') ax4a.invert_yaxis() ax4a.grid(axis='x', alpha=0.3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | # (b) OLS(標準化)vs LASSO の係数比較 ax4b = axes4[1] ols_std = sm.OLS(y, sm.add_constant(X_scaled)).fit(cov_type='HC3') ols_coefs_std = ols_std.params[1:] x_idx = np.arange(len(VAR_NAMES)) width = 0.35 ax4b.barh(x_idx + width/2, ols_coefs_std, width, label='OLS(標準化)', color='#FF8F00', alpha=0.7) ax4b.barh(x_idx - width/2, lasso_coefs, width, label='LASSO', color='#6A1B9A', alpha=0.7) ax4b.axvline(0, color='gray', linestyle='--', linewidth=1.0) ax4b.set_yticks(x_idx) ax4b.set_yticklabels(VAR_NAMES, fontsize=10) ax4b.set_xlabel('係数値(標準化変数)', fontsize=11) ax4b.set_title('OLS(標準化)vs LASSO\n係数の比較', fontsize=11, fontweight='bold') ax4b.legend(fontsize=9) ax4b.invert_yaxis() ax4b.grid(axis='x', alpha=0.3) plt.tight_layout() fig4.savefig(os.path.join(FIG_DIR, '2025_H5_1_fig4_lasso.png'), bbox_inches='tight', dpi=150) plt.close(fig4) print("図4保存: 2025_H5_1_fig4_lasso.png") print("\n全図の生成完了(4枚)") |
# 実行時エラーで途中まで
ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。python 2025_H5_1_shorei.py を実行すると全図(4枚)が再現される。
| データ | 出典 |
|---|---|
| 学生自殺統計 | 厚生労働省 自殺対策白書・警察庁自殺統計 |
| SCカウンセラー配置状況 | 文部科学省 生徒指導・学校安全の取組 |
| 不登校・いじめ統計 | 文部科学省 問題行動等調査 |
| 都道府県別経済・人口統計 | 総務省統計局・内閣府県民経済計算 |
本教育用コードは論文の方法論を再現する目的で合成データを使用。実際の分析には各機関の公表データを参照。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。