9  พื้นฐานเศรษฐมิติและการวิเคราะห์ตัวแบบถดถอย

Modified

April 29, 2026

Keywords

Python for Economics, Computational Economics, Applied Econometrics, Python สำหรับเศรษฐศาสตร์, เศรษฐศาสตร์คำนวณ, เศรษฐมิติเชิงประยุกต์

ในบทนี้เราจะก้าวเข้าสู่หัวใจสำคัญของการวิเคราะห์ข้อมูลทางเศรษฐศาสตร์ นั่นคือการทดสอบความสัมพันธ์ระหว่างตัวแปรด้วย เศรษฐมิติ (Econometrics) โดยใช้ไลบรารี statsmodels ซึ่งถูกออกแบบมาเพื่อให้ผลลัพธ์ (Output) ที่ละเอียดและครบถ้วนตามมาตรฐานงานวิจัย เหมือนกับที่ปรากฏในโปรแกรมทางสถิติอย่าง Stata หรือ EViews

Tipการเตรียมความพร้อมและการติดตั้งไลบรารี

ในการวิเคราะห์เศรษฐมิติเชิงลึก นักศึกษาจำเป็นต้องติดตั้งไลบรารี statsmodels ซึ่งเป็นเครื่องมือมาตรฐานที่ให้ผลการวิเคราะห์ทางสถิติที่ละเอียดและแม่นยำ โดยสามารถดำเนินการติดตั้งผ่าน Terminal ได้ทันทีดังนี้:

สำหรับผู้ใช้ Python ทั่วไป (pip):

pip install statsmodels

สำหรับผู้ใช้ Conda:

conda install -c conda-forge statsmodels

หมายเหตุ: statsmodels จะทำงานร่วมกับ pandas และ numpy ที่เราติดตั้งไปก่อนหน้านี้โดยอัตโนมัติ เพื่อใช้ในการจัดการอาเรย์และตารางข้อมูลทางเศรษฐศาสตร์

หากพิจารณาในมุมของนักเศรษฐศาสตร์และนักวิเคราะห์ข้อมูล statsmodels เป็นไลบรารีที่ทรงพลังและมีความเป็น “วิชาการ” สูงที่สุดในระบบนิเวศของ Python ครับ เพราะมันไม่ได้เน้นแค่การทำนาย (Prediction) เหมือนไลบรารีสาย Machine Learning อย่าง Scikit-learn แต่เน้นไปที่การทดสอบสมมติฐานและการอนุมานทางสถิติ (Inference)

นี่คือความสามารถหลักของ statsmodels ที่ผู้อ่านสามารถนำไปใช้ในงานวิจัยทางเศรษฐศาสตร์ได้:

  1. การประมาณค่าตัวแบบถดถอย (Regression Analysis) นี่คือหัวใจหลักที่นักเศรษฐศาสตร์ใช้งานบ่อยที่สุด:

    • Linear Regression: ไม่ว่าจะเป็น OLS (Ordinary Least Squares), WLS (Weighted), หรือ GLS (Generalized) เพื่อหาความสัมพันธ์เชิงเส้น

    • Generalized Linear Models (GLM): สำหรับข้อมูลที่มีการกระจายตัวแบบอื่น เช่น Logit และ Probit (ใช้บ่อยในเศรษฐศาสตร์จุลภาคเพื่อวิเคราะห์การตัดสินใจแบบ Yes/No) หรือ Poisson Regression สำหรับข้อมูลนับจำนวน

  2. การวิเคราะห์อนุกรมเวลา (Time Series Analysis) statsmodels มีเครื่องมือด้าน Time Series ที่ครบถ้วนมากที่สุดตัวหนึ่ง:

    • Stationarity Tests: การทดสอบความนิ่งของข้อมูล เช่น ADF (Augmented Dickey-Fuller) หรือ KPSS

    • Forecasting Models: รองรับตั้งแต่แบบจำลองพื้นฐานอย่าง AR, MA, ARMA ไปจนถึง ARIMA และ SARIMAX (ที่รวมตัวแปรอิสระภายนอกเข้าไปด้วย)

    • Dynamic Models: รองรับ VAR (Vector Autoregression) สำหรับการวิเคราะห์ความสัมพันธ์ระหว่างตัวแปรอนุกรมเวลาหลายตัวพร้อมกัน

  3. การทดสอบทางสถิติ (Statistical Tests) ช่วยให้นักวิจัยมั่นใจในผลลัพธ์ผ่านการทดสอบต่าง ๆ:

    • Anova (Analysis of Variance): สำหรับการเปรียบเทียบค่าเฉลี่ยระหว่างกลุ่ม

    • Diagnostics Tests: การทดสอบข้อสมมติของตัวแบบถดถอย เช่น การตรวจสอบ Heteroscedasticity (ความแปรปรวนไม่คงที่), Autocorrelation (สหสัมพันธ์ในตัวเอง), และ Normality (การกระจายตัวแบบปกติ)

  4. การจัดการตารางผลลัพธ์ที่เป็นระเบียบ (Summary Tables) จุดเด่นที่ทำให้ statsmodels ต่างจากไลบรารีอื่นคือคำสั่ง .summary() ที่จะพ่นตารางที่มีค่าสถิติครบถ้วน ทั้ง Coefficient, Standard Error, t-statistic, P-value และช่วงความเชื่อมั่น (Confidence Interval) ซึ่งพร้อมสำหรับการนำไปเขียนในรายงานวิจัยทันที

9.1 แบบจำลองการกำหนดราคาสินทรัพย์ทุน (Capital Asset Pricing Model: CAPM)

ในทางเศรษฐศาสตร์การเงิน CAPM ถูกใช้เพื่ออธิบายความสัมพันธ์ระหว่างความเสี่ยงที่ระบบ (Systematic Risk) และผลตอบแทนที่คาดหวังของสินทรัพย์ โดยมีสมการหลักคือ:

\[R_i - R_f = \beta_i (R_m - R_f) + \epsilon_i\]

  • \(R_i - R_f\): ผลตอบแทนส่วนเพิ่มของสินทรัพย์ (Excess Return of Asset)

  • \(R_m - R_f\): ผลตอบแทนส่วนเพิ่มของตลาด (Excess Market Return)

  • \(\beta_i\) (Beta): ตัวชี้วัดความเสี่ยงของสินทรัพย์เมื่อเทียบกับตลาด

9.1.1 การเตรียมข้อมูลด้วย yfinance

เราจะดึงข้อมูลราคาหุ้นรายตัว (เช่น Apple - AAPL) และดัชนีตลาด (เช่น S&P 500 - ^GSPC) ย้อนหลัง 5 ปี เพื่อนำมาคำนวณผลตอบแทน

คลิกเพื่อดูโค้ดไพธอน
import yfinance as yf
import pandas as pd
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt
import seaborn as sns
from IPython.display import display
# กำหนดชื่อหุ้นและดัชนีอ้างอิง
ticker = "AAPL"
market = "^GSPC"

# 1. ดึงข้อมูลย้อนหลัง 5 ปี (รายเดือนเพื่อให้ข้อมูลนิ่งขึ้น)
data = yf.download([ticker, market], period="5y", interval="1mo")['Close']

# เคลียร์ปัญหา Multi-index หากมี
if isinstance(data.columns, pd.MultiIndex):
    data.columns = data.columns.get_level_values(0)

# 2. คำนวณผลตอบแทนรายเดือน (Log Returns)
returns = (pd.util.testing.makeDataFrame() if data.empty else data) # ป้องกันข้อมูลว่าง
returns = 100 * (np.log(data) - np.log(data.shift(1))).dropna()
returns.columns = ['Stock', 'Market']

# 3. กำหนด Risk-free rate (สมมติให้เป็น 0.1% ต่อเดือน หรือประมาณ 1.2% ต่อปี)
rf = 0.1
returns['Stock_Excess'] = returns['Stock'] - rf
returns['Market_Excess'] = returns['Market'] - rf

display(returns.head())
Stock Market Stock_Excess Market_Excess
Date
2021-06-01 9.619712 2.197087 9.519712 2.097087
2021-07-01 6.295837 2.249318 6.195837 2.149318
2021-08-01 4.011432 2.857814 3.911432 2.757814
2021-09-01 -6.896487 -4.873779 -6.996487 -4.973779
2021-10-01 5.700149 6.685818 5.600149 6.585818

9.1.2 การประมาณค่าด้วย OLS Regression

เราจะใช้ statsmodels เพื่อหาค่า \(\beta\) ซึ่งเป็นตัววัดความไวของหุ้นต่อการเปลี่ยนแปลงของตลาด

คลิกเพื่อดูโค้ดไพธอน
# กำหนดตัวแปรตาม (y) และตัวแปรอิสระ (X)
y = returns['Stock_Excess']
X = returns['Market_Excess']
X = sm.add_constant(X) # เพิ่มค่า Alpha (Intercept)

# ประมาณค่าแบบจำลอง
model_capm = sm.OLS(y, X).fit()

# แสดงผลการวิเคราะห์ฉบับเต็ม
display(model_capm.summary())
OLS Regression Results
Dep. Variable: Stock_Excess R-squared: 0.485
Model: OLS Adj. R-squared: 0.476
Method: Least Squares F-statistic: 53.66
Date: Wed, 29 Apr 2026 Prob (F-statistic): 9.13e-10
Time: 21:44:13 Log-Likelihood: -177.76
No. Observations: 59 AIC: 359.5
Df Residuals: 57 BIC: 363.7
Df Model: 1
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
const 0.4042 0.662 0.610 0.544 -0.922 1.730
Market_Excess 1.0621 0.145 7.325 0.000 0.772 1.352
Omnibus: 0.742 Durbin-Watson: 1.458
Prob(Omnibus): 0.690 Jarque-Bera (JB): 0.843
Skew: -0.233 Prob(JB): 0.656
Kurtosis: 2.645 Cond. No. 4.65


Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

9.1.3 การแสดงผลและการตีความทางเศรษฐศาสตร์

การพล็อตเส้น Security Market Line (SML) จะช่วยให้เห็นภาพความสัมพันธ์ระหว่างความเสี่ยงและผลตอบแทนได้ชัดเจน

คลิกเพื่อดูโค้ดไพธอน
plt.figure(figsize=(7, 4))
sns.regplot(x='Market_Excess', y='Stock_Excess', 
            data=returns, 
            scatter_kws={'alpha':0.5}, 
            line_kws={'color':'red', 'label':'CAPM Line'})

# ตกแต่งกราฟ
plt.title(f'CAPM Analysis: {ticker} vs S&P 500', fontsize=14)
plt.xlabel('Excess Market Return (%)')
plt.ylabel('Excess Stock Return (%)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

คลิกเพื่อดูโค้ดไพธอน
# สรุปผลทางเศรษฐศาสตร์
beta = model_capm.params['Market_Excess']
alpha = model_capm.params['const']

print(f"ค่า Beta (ความเสี่ยงเชิงระบบ): {beta:.4f}")
print(f"ค่า Alpha (ผลตอบแทนส่วนเกิน): {alpha:.4f}")
ค่า Beta (ความเสี่ยงเชิงระบบ): 1.0621
ค่า Alpha (ผลตอบแทนส่วนเกิน): 0.4042
Tipสรุปประเด็นสำคัญสำหรับนักศึกษา
  1. Beta (\(\beta\)):

    • ถ้า \(\beta > 1\): หุ้นมีความผันผวนมากกว่าตลาด (Aggressive Stock)

    • ถ้า \(\beta < 1\): หุ้นมีความผันผวนน้อยกว่าตลาด (Defensive Stock)

  2. Alpha (\(\alpha\)): ในทางทฤษฎี CAPM ค่า Alpha ควรเป็น 0 หากค่าเป็นบวกอย่างมีนัยสำคัญ แสดงว่าหุ้นให้ผลตอบแทนดีกว่าที่ความเสี่ยงควรจะเป็น (Abnormal Return)

  3. R-squared: บ่งบอกว่าความผันผวนของหุ้นตัวนี้ถูกอธิบายโดยความเคลื่อนไหวของตลาดได้มากน้อยเพียงใด

9.2 การวิเคราะห์พหุถดถอย (Multiple Linear Regression)

ในหัวข้อนี้ เราจะศึกษาอิทธิพลของระดับการศึกษา (Literacy) และระดับความมั่งคั่ง (Wealth) ที่มีต่อพฤติกรรมการเสี่ยงโชค (Lottery) โดยใช้ข้อมูลเชิงประวัติศาสตร์ฝรั่งเศส

9.2.1 การกำหนดแบบจำลอง (Model Specification)

เราสามารถเขียนความสัมพันธ์ในรูปแบบสมการถดถอยเชิงเส้นได้ดังนี้:

\[Lottery_i = \beta_0 + \beta_1 Literacy_i + \beta_2 Wealth_i + \epsilon_i\]

โดยที่:

  • \(Lottery\) (ตัวแปรตาม): อันดับการซื้อสลากของแต่ละจังหวัด (อันดับน้อย = ซื้อมาก)

  • \(Literacy\) (ตัวแปรอิสระ 1): สัดส่วนการอ่านออกเขียนได้

  • \(Wealth\) (ตัวแปรอิสระ 2): อันดับความมั่งคั่งตามการเสียภาษี (อันดับน้อย = มั่งคั่งสูง)

  • \(\beta_0\): ค่าคงที่ (Intercept)

  • \(\epsilon\): ค่าคลาดเคลื่อน (Error Term)

9.2.2 การประมาณค่าตัวแบบด้วย OLS

เราจะใช้ไลบรารี statsmodels ในการหาค่าสัมประสิทธิ์ \(\beta\)

คลิกเพื่อดูโค้ดไพธอน
import pandas as pd
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt
import seaborn as sns

# 1. โหลดข้อมูล Guerry
dataset = sm.datasets.get_rdataset("Guerry", "HistData").data

# 2. เลือกตัวแปรและจัดการค่าว่าง (ใช้ Wealth แทน Income)
cols = ['Lottery', 'Literacy', 'Wealth']
df = dataset[cols].dropna()

# 3. กำหนดตัวแปรและเพิ่มค่าคงที่ (Constant) เข้าไปในสมการ
y = df['Lottery']
X = df[['Literacy', 'Wealth']]
X = sm.add_constant(X)

# 4. ประมาณค่าด้วยวิธี OLS
model_mlr = sm.OLS(y, X).fit()

# 5. แสดงผลสรุปสถิติ (แนะนำใช้ print สำหรับ Quarto)
display(model_mlr.summary())
OLS Regression Results
Dep. Variable: Lottery R-squared: 0.289
Model: OLS Adj. R-squared: 0.272
Method: Least Squares F-statistic: 16.90
Date: Wed, 29 Apr 2026 Prob (F-statistic): 6.98e-07
Time: 21:44:13 Log-Likelihood: -383.56
No. Observations: 86 AIC: 773.1
Df Residuals: 83 BIC: 780.5
Df Model: 2
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
const 39.7924 8.056 4.940 0.000 23.770 55.815
Literacy -0.3614 0.138 -2.610 0.011 -0.637 -0.086
Wealth 0.4113 0.096 4.273 0.000 0.220 0.603
Omnibus: 3.236 Durbin-Watson: 1.867
Prob(Omnibus): 0.198 Jarque-Bera (JB): 2.423
Skew: -0.259 Prob(JB): 0.298
Kurtosis: 2.362 Cond. No. 216.


Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

9.2.3 การตรวจสอบข้อสมมติ: ค่าคลาดเคลื่อนมีการกระจายตัวแบบปกติหรือไม่?

เพื่อให้การทดสอบสมมติฐาน (\(t\)-test, \(F\)-test) มีความแม่นยำ ค่าคลาดเคลื่อน (\(\epsilon\)) ควรมีการกระจายตัวแบบปกติ (Normality)

คลิกเพื่อดูโค้ดไพธอน
# คำนวณค่า Residuals
residuals = model_mlr.resid

# 1. การตรวจสอบด้วยกราฟ (Visual Inspection)
fig, ax = plt.subplots(2, 1, figsize=(7, 10))

# Histogram และ Kernel Density Estimate
sns.histplot(residuals, kde=True, ax=ax[0], color='seagreen')
ax[0].set_title('Distribution of Residuals')

# Q-Q Plot (หากเรียงตัวตามเส้นตรง แสดงว่าปกติ)
sm.qqplot(residuals, line='s', ax=ax[1])
ax[1].set_title('Normal Q-Q Plot')

plt.tight_layout()
plt.show()

คลิกเพื่อดูโค้ดไพธอน
# 2. การทดสอบทางสถิติอย่างเป็นทางการ (Jarque-Bera Test)
from statsmodels.stats.stattools import jarque_bera
jb_test = jarque_bera(residuals)

print(f"Jarque-Bera Test Results:")
print(f"- Statistic: {jb_test[0]:.4f}")
print(f"- p-value: {jb_test[1]:.4f}")

# สรุปผล
if jb_test[1] > 0.05:
    print("สรุป: ค่าคลาดเคลื่อนมีการกระจายตัวแบบปกติ (ยอมรับ H0)")
else:
    print("สรุป: ค่าคลาดเคลื่อนมีการกระจายตัวไม่เป็นปกติ (ปฏิเสธ H0)")
Jarque-Bera Test Results:
- Statistic: 2.4230
- p-value: 0.2978
สรุป: ค่าคลาดเคลื่อนมีการกระจายตัวแบบปกติ (ยอมรับ H0)
Tipข้อแนะนำเพิ่มเติมสำหรับนักเศรษฐศาสตร์
  • ทิศทางความสัมพันธ์: โปรดสังเกตว่าข้อมูล Wealth และ Lottery ถูกจัดเก็บในรูปของ “อันดับ” (Ranking) ดังนั้น หากค่าสัมประสิทธิ์เป็น บวก หมายความว่าเมื่อรายได้ลดลง (อันดับเพิ่มขึ้น) ปริมาณการซื้อสลากจะลดลง (อันดับเพิ่มขึ้น) ตามไปด้วย

  • การรายงานผล: ในบทความวิจัย นักศึกษาสามารถนำตารางจาก model_mlr.summary() ไปใช้ได้ทันที โดยเน้นรายงานค่า Coefficient, P-value และ Adjusted R-squared เพื่อแสดงถึงคุณภาพของแบบจำลอง

9.3 แบบจำลอง Logit Regression (Generalized Linear Model - GLM)

ในตัวอย่างนี้ เราจะใช้ข้อมูล Guerry เช่นเดิม แต่เราจะสร้างตัวแปรตามใหม่ขึ้นมาคือ “ความเป็นเมืองสูง” (Is_Urban) เพื่อทดสอบว่าระดับการศึกษา (Literacy) และความมั่งคั่ง (Wealth) ส่งผลต่อโอกาสที่จังหวัดนั้นๆ จะเป็นเขตเมืองสำคัญหรือไม่

9.3.1 การกำหนดแบบจำลอง (Model Specification)

ในแบบจำลอง Logit เราจะใช้ฟังก์ชัน Logistic (Link Function) เพื่อบีบให้ผลลัพธ์อยู่ในช่วง [0, 1] เสมอ:

\[P(Y_i = 1) = \frac{1}{1 + e^{-(\beta_0 + \beta_1 Literacy_i + \beta_2 Wealth_i)}}\]

หรือในรูปของ Log-Odds (Logit):

\[\ln\left(\frac{P_i}{1 - P_i}\right) = \beta_0 + \beta_1 Literacy_i + \beta_2 Wealth_i + \epsilon_i\]

9.3.2 การเตรียมข้อมูลและประมาณค่าตัวแบบ

คลิกเพื่อดูโค้ดไพธอน
import pandas as pd
import numpy as np
import statsmodels.api as sm

# 1. โหลดข้อมูล
dataset = sm.datasets.get_rdataset("Guerry", "HistData", cache=True).data
df = dataset[['Region', 'Literacy', 'Wealth']].dropna()

# 2. สร้างตัวแปรตามแบบ Binary (Dummy Variable)
# สมมติว่า Region 'C' (Central) คือเขตความเป็นเมืองสูง (1) นอกนั้นคือ (0)
df['Is_Urban'] = (df['Region'] == 'C').astype(int)

# 3. กำหนดตัวแปรอิสระและเพิ่มค่าคงที่
y = df['Is_Urban']
X = df[['Literacy', 'Wealth']]
X = sm.add_constant(X)

# 4. ประมาณค่าด้วย Logit Model
# วิธีที่ 1: ใช้ Logit โดยตรง
model_logit = sm.Logit(y, X).fit()

# หรือ วิธีที่ 2: ใช้ GLM (Generalized Linear Model) พร้อมระบุ Family
# model_glm = sm.GLM(y, X, family=sm.families.Binomial()).fit()

# 5. แสดงผลการวิเคราะห์
display(model_logit.summary())
Optimization terminated successfully.
         Current function value: 0.403427
         Iterations 7
Logit Regression Results
Dep. Variable: Is_Urban No. Observations: 85
Model: Logit Df Residuals: 82
Method: MLE Df Model: 2
Date: Wed, 29 Apr 2026 Pseudo R-squ.: 0.1938
Time: 21:44:13 Log-Likelihood: -34.291
converged: True LL-Null: -42.534
Covariance Type: nonrobust LLR p-value: 0.0002631
coef std err z P>|z| [0.025 0.975]
const 2.4066 1.367 1.760 0.078 -0.273 5.086
Literacy -0.0938 0.030 -3.126 0.002 -0.153 -0.035
Wealth -0.0163 0.015 -1.078 0.281 -0.046 0.013

9.3.3 การตีความค่า Odds Ratio (หัวใจของ Logit)

เนื่องจากสัมประสิทธิ์ (\(\beta\)) ใน Logit ไม่สามารถตีความตรงๆ ได้เหมือน OLS (เพราะอยู่ในรูป Log-Odds) นักเศรษฐศาสตร์จึงนิยมแปลงค่าให้เป็น Odds Ratio โดยการใช้ฟังก์ชัน Exponential (\(e^\beta\))

คลิกเพื่อดูโค้ดไพธอน
# คำนวณค่า Odds Ratio
odds_ratios = np.exp(model_logit.params)
conf = np.exp(model_logit.conf_int())
conf['Odds Ratio'] = odds_ratios
conf.columns = ['Lower CI', 'Upper CI', 'Odds Ratio']

print("\n--- Odds Ratios Analysis ---")
display(conf)

--- Odds Ratios Analysis ---
Lower CI Upper CI Odds Ratio
const 0.760997 161.803193 11.096475
Literacy 0.858402 0.965608 0.910428
Wealth 0.955009 1.013463 0.983802
Tipสรุปประเด็นสำคัญ
  1. การตีความ Odds Ratio:

    • ถ้า Odds Ratio > 1: หมายความว่าตัวแปรนั้น เพิ่ม โอกาสที่จะเกิดเหตุการณ์ (เช่น การศึกษาเพิ่มขึ้น เพิ่มโอกาสในการเป็นเขตเมือง)

    • ถ้า Odds Ratio < 1: หมายความว่าตัวแปรนั้น ลด โอกาสที่จะเกิดเหตุการณ์

  2. Pseudo R-squared: ใน Logit เราจะไม่มีค่า \(R^2\) ที่แท้จริงเหมือน OLS แต่จะใช้ค่า McFadden’s Pseudo \(R^2\) เพื่อประเมินความสามารถในการจำแนกกลุ่มแทน

  3. Maximum Likelihood Estimation (MLE): ย้ำให้นักศึกษาทราบว่า Logit ไม่ได้คำนวณด้วยวิธี OLS แต่ใช้การหาค่าความน่าจะเป็นสูงสุด (MLE) ซึ่งเป็นมาตรฐานสำหรับตัวแปรตามที่เป็น Binary ครับ