7  การสื่อสารข้อมูลเศรษฐกิจด้วยภาพ

Modified

April 29, 2026

Keywords

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

ในบทก่อนหน้า เราได้เผชิญหน้ากับ “มหาสมุทรของตัวเลข” ที่ดึงมาจาก yfinance หรือแหล่งข้อมูลจริง อย่างไรก็ตาม ตัวเลขเหล่านี้มักจะนิ่งเงียบและยากต่อการตีความหากปราศจากเครื่องมือในการถอดรหัส

คำถามสำคัญที่นักเศรษฐศาสตร์ต้องตอบให้ได้คือ: > เราจะเปลี่ยน “ตัวเลขที่นิ่งเงียบ” ให้กลายเป็น “เรื่องราวทางเศรษฐกิจที่ทรงพลัง” ได้อย่างไร?

7.1 หัวใจของการแปลงข้อมูลสู่ความหมาย

พิจารณาข้อมูลราคาหุ้นหรืออัตราแลกเปลี่ยนที่มีความถี่รายวัน (Daily Data) ตลอด 10 ปี: หากเราแสดงผลผ่านตาราง เราจะเห็นแถวข้อมูลกว่า 2,500 แถว ซึ่งสมองมนุษย์ไม่สามารถประมวลผลรูปแบบ (Pattern) ของมันได้ครบถ้วน

บทบาทของ Visualization คือการสร้าง “ลัดขั้นตอนการรับรู้”:

  • Line Plot (กราฟเส้น): ใช้ติดตาม พลวัต (Dynamics) และแนวโน้มตามเวลา (Trends)

  • Histogram (ฮิสโตแกรม): ใช้สำรวจ พฤติกรรมการกระจายตัว (Distribution) เพื่อดูโอกาสเกิดวิกฤต (Tail Risk)

  • Scatter Plot (กราฟจุด): ใช้ตรวจสอบ ความเชื่อมโยง (Correlation) ระหว่างตัวแปร เช่น ความสัมพันธ์ระหว่างดอกเบี้ยและราคาบ้าน

Noteกรณีศึกษา: จากตัวเลขสู่กราฟวิเคราะห์แนวโน้ม

ลองเปรียบเทียบการมองตัวเลขดิบ กับการใช้ไลบรารีมาตรฐานอย่าง Matplotlib เพื่อสร้างภาพแทนความคิด:

คลิกเพื่อดูโค้ดไพธอน
import matplotlib.pyplot as plt

# ข้อมูลจำลอง: ราคาปิดของสินทรัพย์
prices = [100, 102, 105, 103, 108, 110, 107, 112, 115]

# สร้างกราฟแสดงทิศทาง
plt.figure(figsize=(8, 4))
plt.plot(prices, marker='o', linestyle='-', color='b')
plt.title("Asset Price Analysis (Economic Trend)")
plt.xlabel("Trading Days")
plt.ylabel("Price (USD)")
plt.grid(True, linestyle='--', alpha=0.6) # เพิ่ม Grid เพื่อให้อ่านค่าง่ายขึ้น
plt.show()

สิ่งที่นักเศรษฐศาสตร์ “มองเห็น” ทันทีจากกราฟ:

  1. Trend Awareness: ราคามีแนวโน้มขาขึ้น (Upward Trend) อย่างชัดเจน

  2. Volatility Spotting: มีความผันผวนชั่วคราว (Minor Corrections) ที่จุดที่ 3 และ 6

  3. Support/Resistance: สามารถเห็นระดับราคาที่เป็นแนวต้านหรือแนวรับเบื้องต้นได้

7.1.1 Visualization ในงานเศรษฐศาสตร์ยุคใหม่

ในโลกของการวิเคราะห์สมัยใหม่ เราไม่ได้ใช้กราฟเพื่อความสวยงาม แต่ใช้เพื่อ “พิสูจน์สมมติฐาน”:

  • Macro Analysis: ใช้กราฟเปรียบเทียบ GDP Growth ของหลายประเทศเพื่อดูความเร็วของการฟื้นตัว (Recovery Speed)

  • Market Microstructure: ตรวจสอบความผิดปกติของปริมาณการซื้อขาย (Volume Spikes) ที่อาจสะท้อนการได้รับข้อมูลวงใน

  • Policy Evaluation: เปรียบเทียบข้อมูลก่อนและหลังการประกาศใช้นโยบาย (Pre-Post Analysis)

7.1.2 Visualization ใน Workflow ของนักวิจัย

นักเศรษฐศาสตร์ไม่ได้วาดกราฟเป็นขั้นตอนสุดท้าย แต่เราวาดกราฟ “ตลอดเวลา” ในกระบวนการทำงาน:

flowchart TD
    A[<b>Explore</b><br/>วาดกราฟเบื้องต้น<br/>เพื่อหาความผิดปกติ] --> B[<b>Analyze</b><br/>วิเคราะห์ทางสถิติ<br/>และเศรษฐมิติ]
    B --> C[<b>Validate</b><br/>วาดกราฟ Residuals<br/>เพื่อตรวจสอบ Model]
    C --> D[<b>Communicate</b><br/>สร้างกราฟที่สวยงาม<br/>เพื่อสรุปผลนโยบาย]

    style A fill:#e3f2fd,stroke:#2196f3
    style D fill:#fff3e0,stroke:#e65100

ในบทนี้เราจะเรียนรู้การใช้เครื่องมือมาตรฐานสองระดับ คือ Matplotlib สำหรับการวาดกราฟพื้นฐานที่ยืดหยุ่น และ Seaborn สำหรับการสร้างกราฟสถิติที่สวยงามและวิเคราะห์ข้อมูลได้ลึกซึ้ง

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

ก่อนจะเริ่มสื่อสารข้อมูลด้วยภาพ เราจำเป็นต้องติดตั้งไลบรารีหลักสำหรับวาดกราฟในระบบก่อน โดยเปิด Terminal แล้วใช้คำสั่งดังนี้:

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

conda install matplotlib seaborn

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

pip install matplotlib seaborn
graph TD
    Start[เริ่ม: พิจารณาจำนวนและประเภทตัวแปร] --> Var1{1 ตัวแปร}
    Start --> Var2{2 ตัวแปร}

    %% 1 ตัวแปร
    Var1 --> V1Num[Numeric / ตัวเลข]
    Var1 --> V1Cat[Categorical / หมวดหมู่]
    
    V1Num --> Graph1A[Histogram / KDE Plot]
    style Graph1A fill:#f9f,stroke:#333,stroke-width:2px
    V1Cat --> Graph1B[Bar Chart / Pie Chart]
    style Graph1B fill:#f9f,stroke:#333,stroke-width:2px

    %% 2 ตัวแปร
    Var2 --> V2NumNum[2 Numeric]
    Var2 --> V2CatNum[1 Cat + 1 Num]
    Var2 --> V2CatCat[2 Categorical]

    V2NumNum --> Graph2A[Scatter Plot / Line Graph]
    style Graph2A fill:#bbf,stroke:#333,stroke-width:2px
    
    V2CatNum --> Graph2B[Box Plot / Violin Plot]
    style Graph2B fill:#bbf,stroke:#333,stroke-width:2px
    
    V2CatCat --> Graph2C[Stacked Bar / Heatmap]
    style Graph2C fill:#bbf,stroke:#333,stroke-width:2px

    %% คำอธิบายเพิ่มเติม
    subgraph Legend [คำอธิบายประเภทกราฟ]
        Graph1A -.- Description1[ดูการกระจายตัว / ความเบ้]
        Graph2A -.- Description2[ดูความสัมพันธ์ / แนวโน้ม]
        Graph2B -.- Description3[เปรียบเทียบค่ากลางและความเสี่ยง]
    end
Figure 7.1: แนวทางเลือกกราฟสำหรับข้อมูลเศรษฐกิจ
Tipชนิดและจำนวนตัวแปรที่ต้องการสำหรับกราฟแต่ละแบบ

กรณี 1 ตัวแปร (Univariate Analysis)

  • Numeric (ตัวเลข): เช่น รายได้ (Income) หรือ อัตราเงินเฟ้อ (Inflation)

    • กราฟ: Histogram หรือ KDE Plot

    • สิ่งที่ต้องการ: ข้อมูล Column เดียวที่เป็นตัวเลขต่อเนื่อง

  • Categorical (หมวดหมู่): เช่น ภาค (Region) หรือ อุตสาหกรรม (Industry)

    • กราฟ: Bar Chart (แสดงความถี่ Count)

    • สิ่งที่ต้องการ: ข้อมูลที่เป็นชื่อกลุ่ม เพื่อนำมานับจำนวนสมาชิก

กรณี 2 ตัวแปร (Bivariate Analysis)

  • 2 Numeric (ตัวเลข + ตัวเลข): เช่น ราคาน้ำมัน (X) กับ ดัชนีหุ้น (Y)

    • กราฟ: Scatter Plot (จุดกระจาย) หรือ Line Graph (ถ้า X เป็นเวลา)

    • สิ่งที่ต้องการ: ข้อมูล 2 Column ที่มีจำนวนแถวเท่ากันและ “สัมพันธ์กันตามลำดับแถว”

  • 1 Categorical + 1 Numeric (หมวดหมู่ + ตัวเลข): เช่น วุฒิการศึกษา กับ เงินเดือน

    • กราฟ: Box Plot หรือ Violin Plot

    • สิ่งที่ต้องการ: ข้อมูลกลุ่ม (X) เพื่อแบ่งประเภท และข้อมูลตัวเลข (Y) เพื่อนำมาหาค่าสถิติในกลุ่มนั้น

  • 2 Categorical (หมวดหมู่ + หมวดหมู่): เช่น เพศ กับ การตัดสินใจลงทุน (Yes/No)

    • กราฟ: Heatmap หรือ Stacked Bar Chart

    • สิ่งที่ต้องการ: ข้อมูล 2 กลุ่มมาทำ Crosstabulation (ตารางไขว้) เพื่อดูความหนาแน่น

สำหรับส่วนนี้ ผมแนะนำให้อาจารย์นำเสนอในรูปแบบ “Anatomy of a Plot” เพื่อให้นักศึกษาเข้าใจว่ากราฟ 1 รูปประกอบด้วยชิ้นส่วนอะไรบ้าง (ซึ่งจะช่วยให้เขารู้ว่าจะเรียกใช้ Argument ตัวไหนเพื่อแก้จุดนั้น) โดยเน้นการอธิบายเป็นภาษาไทยแต่ใช้คำศัพท์ Argument เป็นภาษาอังกฤษครับ

7.2 องค์ประกอบของ Matplotlib (Anatomy of a Plot)

ก่อนที่เราจะสั่งปรับแต่งกราฟ เราต้องเข้าใจก่อนว่า Matplotlib มองกราฟเป็น “วัตถุ” (Object) ที่ซ้อนทับกันอยู่ โดยมีองค์ประกอบหลักที่สำคัญดังนี้:

graph TD
    Figure[Figure: พื้นที่รูปภาพทั้งหมด] --> Axes[Axes: พื้นที่วาดกราฟ/แกน]
    Axes --> Title[Title: ชื่อกราฟ]
    Axes --> XAxis[X-Axis: แกนนอน]
    Axes --> YAxis[Y-Axis: แกนตั้ง]
    Axes --> Legend[Legend: คำอธิบายสัญลักษณ์]
    Axes --> Grid[Grid: เส้นตาราง]

7.2.1 ฟังก์ชันและ Argument ที่จำเป็นในการตกแต่ง

ในการสร้างกราฟที่สมบูรณ์ นักเศรษฐศาสตร์ควรทราบฟังก์ชันมาตรฐานเหล่านี้ ซึ่งทำงานภายใต้ระบบ plt (Matplotlib Pyplot):

องค์ประกอบ ฟังก์ชันที่ใช้ Argument ที่สำคัญและน่าสนใจ
Canvas plt.figure() figsize=(w, h) (ขนาดรูป), dpi (ความคมชัด)
Title plt.title() fontsize, fontweight='bold', loc='center/left'
Axis Label plt.xlabel(), plt.ylabel() fontsize, labelpad (ระยะห่างจากแกน)
Grid plt.grid() visible=True, linestyle='--', alpha=0.5 (ความโปร่งแสง)
Legend plt.legend() loc='best/upper right', frameon=False
Plot Style plt.plot() color, linewidth, linestyle, marker (จุดบนเส้น)

7.2.2 ตัวอย่างการร้อยเรียง Argument (Step-by-Step)

เพื่อให้เห็นภาพกระบวนการ (Process) การปรับแต่งข้อมูลที่เราเตรียมไว้ เราจะนำ Argument ต่างๆ มาประกอบกันดังนี้:

คลิกเพื่อดูโค้ดไพธอน
import matplotlib.pyplot as plt
import numpy as np

# 1. Prepare Data
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

# 2. Canvas Preparation (Step 1)
plt.figure(figsize=(10, 5), dpi=100)

# 3. Plotting with Line Styling (Step 2)
plt.plot(x, y1, color = 'tab:blue', 
         linewidth = 2, linestyle = '-',  
         label = 'Cyclical Trend A')
plt.plot(x, y2, color='tab:red', 
        linewidth = 2, linestyle = '--', 
        label = 'Cyclical Trend B')

# 4. Professional Customization (Step 3)
plt.title('Economic Cycle Simulation', fontsize = 16, 
          fontweight = 'bold', loc = 'left')
plt.xlabel('Time Period (Years)', fontsize = 12)
plt.ylabel('Percentage Change (%)', fontsize = 12)
plt.legend(loc = 'upper right', frameon = True)
plt.grid(True, linestyle = ':', alpha = 0.6)

# 5. Output Rendering (Step 4)
plt.tight_layout() # จัดระเบียบองค์ประกอบไม่ให้ทับกัน
plt.show()

7.3 กราฟชนิดต่างๆ ด้วย matplotlib

7.3.1 กรณี 1 ตัวแปร (Univariate Analysis)

1.1 Numeric: Histogram / KDE Plot

ใช้ดูการกระจายตัวของข้อมูล เช่น การกระจายตัวของรายได้ประชากร

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

# จำลองข้อมูลรายได้ (Income)
income_data = np.random.lognormal(mean=10, sigma=0.5, size=1000)

plt.figure(figsize=(8, 5))

# ใช้ Seaborn วาด Hist + KDE
sns.histplot(data=income_data, 
             kde=True,                  # แสดงเส้นความหนาแน่น (Kernel Density Estimate)
             color='skyblue',           # กำหนดสี
             bins=30,                   # จำนวนแท่ง
             stat='density')            # แสดงผลเป็นความหนาแน่นแทนความถี่

# ปรับแต่งด้วย Matplotlib (English Labels)
plt.title('Income Distribution Analysis', fontsize=14)
plt.xlabel('Annual Income (USD)')
plt.ylabel('Density')
plt.show()

1.2 Categorical: Bar Chart

ใช้เปรียบเทียบจำนวนหรือมูลค่าแยกตามกลุ่ม เช่น มูลค่าส่งออกแยกตามอุตสาหกรรม

คลิกเพื่อดูโค้ดไพธอน
# ข้อมูลจำลอง
sectors = ['Agriculture', 'Manufacturing', 'Services', 'Tech']
exports = [150, 450, 300, 500]

plt.figure(figsize=(8, 5))

# วาดกราฟแท่ง
plt.bar(x=sectors,                      # ข้อมูลแกน X (หมวดหมู่)
        height=exports,                 # ข้อมูลแกน Y (ค่าตัวเลข)
        color='tab:green',              # กำหนดสี
        alpha=0.8)                      # ความโปร่งแสง

plt.title('Export Value by Sector', fontsize=14)
plt.xlabel('Economic Sectors')
plt.ylabel('Value (Billion USD)')
plt.show()

7.3.2 กรณี 2 ตัวแปร (Bivariate Analysis)

2.1 2 Numeric: Scatter Plot / Line Graph

ใช้ดูความสัมพันธ์ (Scatter) หรือแนวโน้มตามเวลา (Line) เช่น ความสัมพันธ์ระหว่างราคาน้ำมันกับดัชนีหุ้น

คลิกเพื่อดูโค้ดไพธอน
import yfinance as yf

# ดึงข้อมูลจริงจาก yfinance (บทที่ 6)
df = yf.download(["CL=F", "^SET.BK"], period="1y")['Close'].ffill()

plt.figure(figsize=(8, 6))

# ใช้ Seaborn วาด Scatter + Regression Line
sns.regplot(x=df['CL=F'],               # ตัวแปรอิสระ (Oil Price)
            y=df['^SET.BK'],            # ตัวแปรตาม (SET Index)
            scatter_kws={'alpha':0.3},  # ปรับแต่งจุด (ความจาง)
            line_kws={'color':'red'})   # ปรับแต่งเส้น (สีแดง)

plt.title('Correlation: Oil Prices vs Stock Market')
plt.xlabel('Crude Oil Price (USD)')
plt.ylabel('SET Index (Points)')
plt.show()

2.2 1 Categorical + 1 Numeric: Box Plot

ใช้เปรียบเทียบค่าสถิติระหว่างกลุ่ม เช่น ความผันผวนของผลตอบแทนหุ้นแต่ละกลุ่มอุตสาหกรรม

คลิกเพื่อดูโค้ดไพธอน
# สมมติข้อมูลผลตอบแทน (Returns) ของ 3 กลุ่มอุตสาหกรรม
data = {
    'Sector': ['Energy']*100 + ['Tech']*100 + ['Bank']*100,
    'Returns': np.concatenate([np.random.normal(0, 2, 100), 
                               np.random.normal(0, 5, 100), 
                               np.random.normal(0, 1, 100)])
}

plt.figure(figsize=(8, 5))

# วาด Box Plot
sns.boxplot(x='Sector',                 # ข้อมูลกลุ่ม (แกน X)
            y='Returns',                # ข้อมูลตัวเลข (แกน Y)
            data=data,                  # แหล่งข้อมูล
            palette='Set3')             # ชุดสีที่ใช้

plt.title('Volatility Comparison by Sector')
plt.ylabel('Daily Returns (%)')
plt.show()

2.3 2 Categorical: Heatmap

ใช้ดูความหนาแน่นหรือความสัมพันธ์ของ 2 กลุ่มข้อมูล เช่น การตัดสินใจซื้อ (Yes/No) แยกตามช่วงอายุ

คลิกเพื่อดูโค้ดไพธอน
# จำลองข้อมูลตารางไขว้ (Crosstab)
matrix_data = np.array([[20, 50, 10], [40, 30, 60]]) 
age_groups = ['Young', 'Middle', 'Senior']
decision = ['Buy', 'Not Buy']

plt.figure(figsize=(8, 4))

# วาด Heatmap
sns.heatmap(data=matrix_data, 
            annot=True,                 # แสดงตัวเลขในช่อง (Annotation)
            fmt="d",                    # รูปแบบตัวเลข (Decimal)
            xticklabels=age_groups,      # ชื่อกลุ่มแกน X
            yticklabels=decision,        # ชื่อกลุ่มแกน Y
            cmap='YlGnBu')              # โทนสีจากเหลืองไปน้ำเงิน

plt.title('Consumer Decision by Age Group')
plt.show()

7.4 การวาดกราฟแบบจำลองทางทฤษฎี (Matplotlib)

นักเศรษฐศาสตร์มักเริ่มจากการวาดกราฟเพื่ออธิบายแบบจำลอง (Theoretical Modeling) เช่น เส้นอุปสงค์และอุปทาน เราจะใช้ Matplotlib ในการกำหนดฟังก์ชันและวาดเส้นโค้งเหล่านี้

คลิกเพื่อดูโค้ดไพธอน
import matplotlib.pyplot as plt
import numpy as np

# 1. สร้างข้อมูลราคา (Price)
price = np.linspace(10, 100, 100)

# 2. กำหนดฟังก์ชัน Demand และ Supply
demand = 120 - price    
supply = price + 20     

# 3. วาดกราฟ
plt.figure(figsize=(7, 4))
plt.plot(demand, price, label='Demand Curve', color='blue', linewidth=2)
plt.plot(supply, price, label='Supply Curve', color='red', linewidth=2)

# 4. ตกแต่งกราฟด้วยภาษาอังกฤษ (Professional Elements)
plt.title('Market Equilibrium: Demand and Supply', fontsize=14)
plt.xlabel('Quantity (Q)')
plt.ylabel('Price (P)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

##Seaborn สำหรับกราฟสถิติทางเศรษฐศาสตร์

เมื่อเราเข้าใจโครงสร้างของ Matplotlib แล้ว ขั้นตอนต่อไปคือการใช้ Seaborn ซึ่งเป็นไลบรารีที่ถูกสร้างขึ้นมาเพื่อ “งานวิเคราะห์ข้อมูลสถิติ” โดยเฉพาะ ทำไมเราถึงต้องใช้ Seaborn?

  • Statistical Built-in: คำนวณค่าสถิติ (เช่น Mean, Confidence Interval, Regression Line) ให้โดยอัตโนมัติ

  • Pandas Friendly: ออกแบบมาให้ทำงานกับ DataFrame ได้ทันที เพียงแค่ระบุชื่อคอลัมน์

  • Aesthetic Defaults: มีชุดสีและหน้าตากราฟที่ทันสมัย (Modern Look) เหมาะกับรายงานวิจัย

7.4.1 การวิเคราะห์การกระจายตัว (Distribution Analysis)

นักเศรษฐศาสตร์ใช้กราฟชนิดนี้เพื่อดู “ลักษณะของข้อมูล” เช่น ความเหลื่อมล้ำของรายได้ หรือความโด่งของอัตราเงินเฟ้อ

ประเภทข้อมูล: 1 Numeric (ตัวเลข 1 ชุด)

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

# จำลองข้อมูลอัตราเงินเฟ้อ (Inflation Rate)
inflation = np.random.normal(loc=2.5, scale=1.2, size=1000)

# Step 1 & 2: Canvas & Plotting
plt.figure(figsize=(8, 5))
sns.histplot(inflation, kde=True, color='darkblue', stat="density", alpha=0.4)

# Step 3: Customization (English Labels)
plt.title('Distribution of Annual Inflation Rates', fontsize=14)
plt.xlabel('Inflation Rate (%)')
plt.ylabel('Density')

# Step 4: Output
plt.show()

7.4.2 การเปรียบเทียบความผันผวนระหว่างกลุ่ม (Volatility Comparison)

เราใช้ Box Plot เพื่อดูค่ากลาง (Median) และการกระจายตัว (Spread) รวมถึงค่าผิดปกติ (Outliers) เพื่อเปรียบเทียบความเสี่ยงของแต่ละสินทรัพย์

ประเภทข้อมูล: 1 Categorical (หมวดหมู่) + 1 Numeric (ตัวเลข)

คลิกเพื่อดูโค้ดไพธอน
# จำลองข้อมูลผลตอบแทนรายวัน (Daily Returns) ของ 3 สินทรัพย์
assets = ['Gold', 'Stock', 'Bitcoin']
data = {
    'Asset': np.repeat(assets, 100),
    'Returns': np.concatenate([
        np.random.normal(0.02, 0.5, 100), # Gold
        np.random.normal(0.05, 1.5, 100), # Stock
        np.random.normal(0.10, 4.0, 100)  # Bitcoin
    ])
}

plt.figure(figsize=(9, 5))

# ใช้ Argument 'hue' เพื่อแยกสีตามกลุ่มข้อมูลอัตโนมัติ
sns.boxplot(x='Asset', y='Returns', data=data, palette='Set3', hue='Asset', legend=False)

plt.title('Asset Returns Volatility Comparison', fontsize=14)
plt.ylabel('Daily Return (%)')
plt.show()

7.4.3 การวิเคราะห์ความสัมพันธ์เชิงเส้น (Relationship Analysis)

การดูความสัมพันธ์ระหว่างตัวแปร เช่น รายได้กับการบริโภค เราจะใช้ Scatter Plot พร้อมการวาดเส้นแนวโน้ม (Regression Line)

ประเภทข้อมูล: 2 Numeric (ตัวเลข 2 ชุดที่สัมพันธ์กัน)

คลิกเพื่อดูโค้ดไพธอน
# จำลองข้อมูล Income vs Consumption
income = np.linspace(20000, 100000, 50)
consumption = 0.7 * income + np.random.normal(5000, 3000, 50)

plt.figure(figsize=(8, 6))

# sns.regplot จัดการวาดจุดกระจายและคำนวณเส้นถดถอยให้ในบรรทัดเดียว
sns.regplot(x=income, y=consumption, 
            scatter_kws={'color': 'tab:blue', 'alpha': 0.5},
            line_kws={'color': 'tab:red', 'lw': 2})

plt.title('Consumption Function Analysis', fontsize=14)
plt.xlabel('Disposable Income')
plt.ylabel('Consumption Expenditure')
plt.show()

7.4.4 การวิเคราะห์ความหนาแน่นเชิงปริมาณ (Heatmap)

ใช้สำหรับดูความสัมพันธ์ (Correlation) หรือความหนาแน่นของข้อมูล 2 มิติ เช่น ค่าสหสัมพันธ์ระหว่างราคาสินทรัพย์ต่างๆ ในพอร์ตการลงทุน

ประเภทข้อมูล: 2 Categorical (หรือ Matrix ของ Numeric)

คลิกเพื่อดูโค้ดไพธอน
import pandas as pd

# จำลองตารางสหสัมพันธ์ (Correlation Matrix) ของตัวแปรเศรษฐกิจ
data_corr = {
    'SET_Index': [1.00, 0.65, -0.20],
    'Oil_Price': [0.65, 1.00, 0.15],
    'Gold_Price': [-0.20, 0.15, 1.00]
}
df_corr = pd.DataFrame(data_corr, index=['SET_Index', 'Oil_Price', 'Gold_Price'])

plt.figure(figsize=(7, 5))

# annot=True แสดงตัวเลข, cmap='coolwarm' ใช้สีแดง-น้ำเงินสื่อความหมาย
sns.heatmap(df_corr, annot=True, cmap='coolwarm', center=0, fmt='.2f')

plt.title('Economic Indicators Correlation Matrix', fontsize=14)
plt.show()

Tipสรุปการเลือกใช้ Argument สำหรับนักเศรษฐศาสตร์

เพื่อให้กราฟในงานวิจัยของคุณดูเป็นมืออาชีพ ควรให้ความสำคัญกับ Argument ต่อไปนี้:

  1. alpha: ใช้ปรับความโปร่งแสงเมื่อมีข้อมูลจำนวนมาก เพื่อให้เห็นความหนาแน่นของจุด

  2. palette: เลือกใช้ชุดสีที่เหมาะสม (เช่น Set2, viridis, RdBu) เพื่อช่วยแยกกลุ่มข้อมูลให้ชัดเจน

  3. hue: ตัวช่วยที่ทรงพลังที่สุดใน Seaborn สำหรับการเพิ่มมิติของข้อมูล (มิติที่ 3) ลงในกราฟ 2 มิติ

  4. lw (linewidth) และ ls (linestyle): ใช้กำหนดลักษณะเส้นให้แตกต่างกันเมื่อต้องเปรียบเทียบหลายเส้นในกราฟเดียว

สำหรับการพล็อตข้อมูล Time Series จาก yfinance ในงานเศรษฐศาสตร์ถือเป็นกรณีที่พบบ่อยที่สุดครับ ความพิเศษของข้อมูลชนิดนี้คือมี Index เป็นวันที่ (Datetime) ซึ่งเราต้องใช้ประโยชน์จากจุดนี้เพื่อให้แกน X แสดงลำดับเวลาได้อย่างถูกต้อง

ผมเรียบเรียงเนื้อหาส่วนนี้ต่อจาก Heatmap เพื่อให้อาจารย์นำไปใส่ในหนังสือได้เลยครับ โดยจะเน้นขั้นตอนการเตรียมข้อมูล (ffill) และการจัดการแกนวันที่ครับ

7.4.5 การวิเคราะห์ข้อมูลอนุกรมเวลา (Time Series Analysis)

ในวิชาเศรษฐศาสตร์มหภาคและการเงิน ข้อมูลส่วนใหญ่อยู่ในรูปอนุกรมเวลา (Time Series) เช่น ดัชนีราคาหุ้นหรือราคาสินค้าโภคภัณฑ์ การพล็อตข้อมูลชนิดนี้มีจุดสำคัญคือการจัดการกับ Missing Values (เช่น วันหยุดตลาดหุ้น) และการปรับแต่งแกนวันที่ให้ดูเป็นมืออาชีพ

ประเภทข้อมูล: 1 Numeric (ค่าของสินทรัพย์) ที่ผูกกับ Datetime Index

คลิกเพื่อดูโค้ดไพธอน
import yfinance as yf
import matplotlib.pyplot as plt
import seaborn as sns

# 1. Prepare Data: ดึงข้อมูลและจัดการค่าว่าง
# เราจะดึงข้อมูลราคาทองคำ (GC=F) ย้อนหลัง 2 ปี
gold_df = yf.download("GC=F", period="2y")['Close']

# สำคัญมาก: ข้อมูล Time Series ต้องทำการ Forward Fill เพื่อไม่ให้เส้นกราฟขาดช่วง
gold_price = gold_df.ffill().dropna()

# 2. Canvas & Plotting
plt.figure(figsize=(10, 5))

# สำหรับ Time Series เราใช้ plt.plot() พื้นฐาน หรือ sns.lineplot() ก็ได้
# ในที่นี้ใช้ plt.plot เพื่อความรวดเร็วเนื่องจากข้อมูลมี Index เป็นวันที่อยู่แล้ว
plt.plot(gold_price.index, gold_price.values, 
         color='goldenrod', 
         linewidth=2, 
         label='Gold Spot Price')

# 3. Customization (English Labels)
plt.title('Gold Price Trend Analysis (2-Year Period)', fontsize=14, fontweight='bold')
plt.xlabel('Date')
plt.ylabel('Price (USD/Ounce)')
plt.legend(loc='upper left')
plt.grid(True, linestyle=':', alpha=0.6)

# ปรับให้แกนวันที่เอียงเล็กน้อยเพื่อให้ไม่อัดแน่นจนเกินไป
plt.xticks(rotation=45)

# 4. Output
plt.tight_layout()
plt.show()

7.4.6 การพล็อตข้อมูลที่มีหลายหน่วยวัด (Dual Axis Chart)

บ่อยครั้งที่นักเศรษฐศาสตร์ต้องการเปรียบเทียบตัวแปร 2 ตัวที่มีหน่วยต่างกัน เช่น ราคาน้ำมัน (USD) และ ดัชนีหุ้น (Points) หากพล็อตลงในแกนเดียวจะมองไม่เห็นความเคลื่อนไหว เราจึงต้องใช้เทคนิค Twin Axes

คลิกเพื่อดูโค้ดไพธอน
# ดึงข้อมูลน้ำมัน (Oil) และดัชนีตลาดหุ้นไทย (SET)
data = yf.download(["CL=F", "^SET.BK"], period="1y")['Close'].ffill()

# Step 1: สร้าง Figure และ Axis แรก (แกนซ้าย)
fig, ax1 = plt.subplots(figsize=(10, 5))

# Plot ราคาน้ำมันที่แกนซ้าย
ax1.plot(data.index, data['CL=F'], color='tab:blue', label='Crude Oil (Left)')
ax1.set_xlabel('Date')
ax1.set_ylabel('Oil Price (USD/Barrel)', color='tab:blue')
ax1.tick_params(axis='y', labelcolor='tab:blue')

# Step 2: สร้าง Axis ที่สองที่ใช้แกน X ร่วมกัน (แกนขวา)
ax2 = ax1.twinx()
ax2.plot(data.index, data['^SET.BK'], color='tab:red', label='SET Index (Right)')
ax2.set_ylabel('SET Index (Points)', color='tab:red')
ax2.tick_params(axis='y', labelcolor='tab:red')

# Step 3: Customization
plt.title('Comparison: Crude Oil Prices vs. Thai Stock Market Index')
fig.tight_layout()
plt.show()

Warningข้อควรระวังสำหรับข้อมูล Time Series จาก yfinance:
  1. Datetime Alignment: เมื่อดึงข้อมูลจากสินทรัพย์ที่อยู่คนละตลาด (เช่น ทองคำในนิวยอร์ก และหุ้นไทย) วันหยุดจะไม่ตรงกัน การใช้ .ffill() (Forward Fill) คือมาตรฐานที่นักเศรษฐศาสตร์ใช้เพื่อให้ข้อมูลซิงค์กันในทุกๆ วันที่มีการซื้อขายในตลาดใดตลาดหนึ่ง

  2. Visual Overload: หากข้อมูลมีระยะเวลายาวมาก (เช่น 10 ปี) การพล็อตรายวันจะทำให้กราฟดูแน่นเกินไป อาจารย์อาจจะแนะนำให้นักศึกษาใช้ .resample('M').mean() เพื่อยุบข้อมูลเป็นรายเดือนก่อนพล็อต เพื่อดูแนวโน้ม (Trend) ที่ชัดเจนขึ้น

7.5 Special Topic: การสร้างฟังก์ชันวาดแบบจำลองทางเศรษฐศาสตร์

ในทางเศรษฐศาสตร์ เรามักต้องวาดกราฟเส้นตรงหรือเส้นโค้งเพื่ออธิบายทฤษฎี เช่น Demand-Supply หรือ IS-LM หากเราต้องเขียนโค้ดวาดใหม่ทุกครั้งที่มีการเปลี่ยนค่าพารามิเตอร์ (เช่น ภาษีเพิ่มขึ้น หรือ ดอกเบี้ยลดลง) จะทำให้เสียเวลามาก

💡 Modern Approach: เราจะสร้าง “ฟังก์ชัน” (Function) ขึ้นมาเพื่อรับค่าพารามิเตอร์ทางเศรษฐศาสตร์ และให้ Python วาดกราฟให้เราโดยอัตโนมัติ

7.5.1 การสร้างฟังก์ชันวาดกราฟ Demand-Supply

เราจะสร้างฟังก์ชันที่ชื่อว่า plot_market_equilibrium เพื่อวาดจุดสมดุลของตลาด

ขั้นตอนของการจำลองทฤษฎี

graph LR
    A[กำหนดสมการทางเศรษฐศาสตร์] --> B[สร้างฟังก์ชันใน Python]
    B --> C[ใส่พารามิเตอร์/นโยบาย]
    C --> D[แสดงผลกราฟจำลอง]
    D --> E{วิเคราะห์ผลกระทบ?}

คลิกเพื่อดูโค้ดไพธอน
import matplotlib.pyplot as plt
import numpy as np

def plot_market(a, b, c, d):
    """
    ฟังก์ชันวาด Demand-Supply
    Demand: P = a - bQ
    Supply: P = c + dQ
    """
    Q = np.linspace(0, 100, 100)
    
    # 1. คำนวณราคาสินค้าตามทฤษฎี
    P_demand = a - b * Q
    P_supply = c + d * Q
    
    # 2. คำนวณจุดสมดุล (Equilibrium) ทางคณิตศาสตร์
    # เนื่องจากเป็นสมการเส้นตรง เราแก้สมการตรงๆ จะแม่นยำกว่า
    Q_star = (a - c) / (b + d)
    P_star = a - b * Q_star
    
    plt.plot(Q, P_demand, label='Demand', color='blue', linewidth=2)
    plt.plot(Q, P_supply, label='Supply', color='red', linewidth=2)
    
    # 3. ตรวจสอบว่าจุดสมดุลอยู่ในช่วงที่วาดหรือไม่ (Robust Check)
    if 0 <= Q_star <= 100:
        # วาดจุดสมดุลและใส่คำอธิบาย
        plt.scatter(Q_star, P_star, color='black', s=100, zorder=5)
        plt.annotate(f'Equilibrium\nQ*={Q_star:.1f}\nP*={P_star:.1f}', 
                     xy=(Q_star, P_star), xytext=(Q_star+10, P_star+10),
                     arrowprops=dict(arrowstyle='->'))
    else:
        print("Warning: Equilibrium is outside the plotted range (0-100).")

    plt.title("Market Equilibrium: Demand and Supply")
    plt.xlabel("Quantity (Q)")
    plt.ylabel("Price (P)")
    plt.ylim(0, max(a, c + d*100))
    plt.legend()
    plt.grid(True, linestyle='--', alpha=0.5)
    plt.show()
Warningข้อควรระวังทางการคำนวณ (Computational Note):

ในการสร้างแบบจำลองจำลองด้วยคอมพิวเตอร์ บางครั้งค่าพารามิเตอร์ที่เรากำหนด (เช่น Cost_Shock ที่สูงเกินไป) อาจทำให้จุดสมดุลหลุดออกไปนอกขอบเขตที่เรากำลังพิจารณา ในทางเศรษฐศาสตร์สิ่งนี้สะท้อนถึงสภาวะวิกฤตที่รุนแรงจนระบบเศรษฐกิจเดิมไม่สามารถหาจุดสมดุลใหม่ได้ในช่วงเวลาที่กำหนด นักเศรษฐศาสตร์จึงต้องตรวจสอบขอบเขตของข้อมูล (Range of Y) ให้ครอบคลุมการเปลี่ยนแปลงของนโยบายเสมอ

คลิกเพื่อดูโค้ดไพธอน
# เรียกใช้งานฟังก์ชัน (ทดลองปรับเปลี่ยนพารามิเตอร์ได้ที่นี่)
plot_market(a=100, b=0.8, c=10, d=0.2)

7.5.2 การสร้างฟังก์ชันจำลองแบบจำลองทางเศรษฐศาสตร์ (Theory-based Simulation)

ในบทก่อนหน้านี้ เราเน้นการสร้างกราฟจาก “ข้อมูล” (Data-driven) อย่างไรก็ตาม บทบาทที่สำคัญอีกประการหนึ่งของนักเศรษฐศาสตร์คือการทำ Simulation เพื่อทดสอบทฤษฎีหรือคาดการณ์ผลกระทบของนโยบาย (Policy Shocks) ก่อนที่จะเกิดขึ้นจริง

ในหัวข้อนี้ เราจะเรียนรู้วิธีการเปลี่ยนสมการทางเศรษฐศาสตร์ที่ซับซ้อนให้กลายเป็นฟังก์ชันใน Python เพื่อสร้างแบบจำลอง IS-LM (Investment-Saving / Liquidity preference-Money supply) ซึ่งเป็นหัวใจสำคัญของเศรษฐศาสตร์มหภาคระยะสั้น

  1. ความเชื่อมโยงระหว่างสมการและอัลกอริทึม แบบจำลอง IS-LM ประกอบด้วยสมดุลใน 2 ตลาดหลัก:

    • ตลาดสินค้า (IS Curve): ความสัมพันธ์ระหว่างรายได้ (\(Y\)) และอัตราดอกเบี้ย (\(r\)) ที่ทำให้การออมเท่ากับการลงทุน

    • ตลาดเงิน (LM Curve): จุดที่อุปสงค์ต่อเงินเท่ากับอุปทานเงินที่แท้จริง (\(M/P\))

  2. การเขียนฟังก์ชัน Python เพื่อหาจุดสมดุล เราจะใช้ไลบรารี NumPy สำหรับการคำนวณเชิงตัวเลข และ Matplotlib สำหรับการแสดงผล โดยออกแบบฟังก์ชันให้รับพารามิเตอร์ทางนโยบาย เช่น การใช้จ่ายภาครัฐ (\(G\)) และปริมาณเงิน (\(M\)) เพื่อดูการขยับของเส้นกราฟ (Shifts)

คลิกเพื่อดูโค้ดไพธอน
import numpy as np
import matplotlib.pyplot as plt

def simulate_is_lm(G, T, M, P, c=0.8, b=0.2, k=0.5, h=10):
    # 1. กำหนดช่วงการมองเห็น
    Y_min, Y_max = 100, 1500
    Y = np.linspace(Y_min, Y_max, 100)
    
    # คำนวณเส้น IS และ LM
    is_intercept = (G - c * T) / b
    is_slope = (1 - c) / b
    r_is = is_intercept - is_slope * Y
    
    lm_intercept = (M / P) / h
    lm_slope = k / h
    r_lm = (lm_slope * Y) - lm_intercept
    
    # 2. คำนวณจุดสมดุลทางคณิตศาสตร์
    denominator = is_slope + lm_slope
    Y_star = (is_intercept + lm_intercept) / denominator
    r_star = is_intercept - is_slope * Y_star
    
    plt.plot(Y, r_is, label='IS Curve', color='#1f77b4', linewidth=2.5)
    plt.plot(Y, r_lm, label='LM Curve', color='#d62728', linewidth=2.5)
    
    # --- ส่วนตรวจสอบการตัดกัน (Equilibrium Check) ---
    if Y_min <= Y_star <= Y_max and r_star >= 0:
        # กรณีตัดกันในขอบเขตที่เหมาะสม
        plt.scatter(Y_star, r_star, color='black', s=100, zorder=5)
        plt.axvline(x=Y_star, color='gray', linestyle='--', alpha=0.4)
        plt.axhline(y=r_star, color='gray', linestyle='--', alpha=0.4)
        plt.annotate(f'Equilibrium\nY*={Y_star:.1f}\nr*={r_star:.2f}', 
                     xy=(Y_star, r_star), xytext=(Y_star+100, r_star+5),
                     arrowprops=dict(arrowstyle='->', lw=1.5))
    else:
        # กรณีไม่ตัดกันในขอบเขตที่กำหนด (เตือนบนกราฟ)
        plt.text((Y_min+Y_max)/2, 20, 
                 "⚠️ Equilibrium Out of Range\nor Economic Infeasibility", 
                 color='red', fontsize=12, fontweight='bold',
                 ha='center', bbox=dict(facecolor='white', alpha=0.8, edgecolor='red'))
        
        print(f"Note: Calculated Y* is {Y_star:.1f}. Consider adjusting parameters.")

    plt.title(f'IS-LM Model Analysis (G={G}, M={M})', fontsize=14)
    plt.xlabel('Real Income (Y)')
    plt.ylabel('Interest Rate (r)')
    plt.xlim(Y_min, Y_max)
    plt.ylim(0, max(25, r_is.max(), r_lm.max()) * 0.8) 
    
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.show()
คลิกเพื่อดูโค้ดไพธอน
# ทดลองรันแบบจำลอง: กรณีใช้นโยบายการคลังแบบขยายตัว (เพิ่ม G)
simulate_is_lm(G=250, T=100, M=1000, P=2)
Note: Calculated Y* is 857.1. Consider adjusting parameters.

  1. การตีความผลลัพธ์เชิงนโยบาย (Economic Interpretation) จากการใช้ฟังก์ชันข้างต้น นักศึกษาจะสังเกตเห็นประเด็นสำคัญที่ตำราทฤษฎีมักกล่าวถึง:
  • Fiscal Policy: เมื่อปรับค่า G เพิ่มขึ้น เส้น IS จะ Shift ไปทางขวา ส่งผลให้ทั้งรายได้ (\(Y\)) และดอกเบี้ย (\(r\)) เพิ่มสูงขึ้น

  • Monetary Policy: เมื่อปรับปริมาณเงิน M เพิ่มขึ้น เส้น LM จะ Shift ลง (ไปทางขวา) ทำให้รายได้เพิ่มขึ้นแต่ดอกเบี้ยลดลง

  • Crowding-out Effect: เราสามารถคำนวณได้ทันทีว่าการเพิ่ม G ส่งผลให้ดอกเบี้ยพุ่งขึ้นจนไปลดการลงทุนภาคเอกชนได้มากน้อยเพียงใดผ่านการเปลี่ยนค่าพารามิเตอร์ b

7.5.3 แบบจำลอง AS-AD กับการวิเคราะห์ภาวะเงินเฟ้อและผลผลิต

หลังจากที่เราเข้าใจสมดุลในตลาดสินค้าและตลาดเงินผ่าน IS-LM แล้ว ขั้นตอนถัดไปคือการนำระดับราคา (\(P\)) มาพิจารณาเป็นตัวแปรตาม เพื่อสร้างแบบจำลอง AS-AD ซึ่งจะช่วยให้เราวิเคราะห์ปรากฏการณ์ทางเศรษฐกิจที่ซับซ้อน เช่น ภาวะเงินเฟ้อ (Inflation) และภาวะเศรษฐกิจถดถอย (Recession) ได้

  1. องค์ประกอบของแบบจำลอง

    • Aggregate Demand (AD): เส้นอุปสงค์รวมที่แสดงความสัมพันธ์ผกผันระหว่างระดับราคากับผลผลิต (สืบเนื่องมาจากจุดสมดุลของ IS-LM ที่เปลี่ยนไปตามระดับราคา)

    • Aggregate Supply (AS): เส้นอุปทานรวม ในที่นี้เราจะเน้น Short-Run AS (SRAS) ซึ่งแสดงความสัมพันธ์ทิศทางเดียวกันระหว่างระดับราคากับผลผลิตตามทฤษฎีความหนืดของราคา (Sticky Price)

  2. การสร้างแบบจำลอง AS-AD ด้วย Python เราจะสร้างฟังก์ชัน simulate_as_ad เพื่อจำลองการขยับของเส้น AD และ AS เมื่อเกิดเหตุการณ์ต่าง ๆ ในระบบเศรษฐกิจ

คลิกเพื่อดูโค้ดไพธอน
import numpy as np
import matplotlib.pyplot as plt

def simulate_as_ad(G, M, Cost_Shock):
    # 1. ขยายช่วง Y ให้กว้างขึ้นเพื่อให้แน่ใจว่าเกิดจุดตัด
    Y = np.linspace(10, 2000, 2000) 
    
    # 2. สมการ AD และ AS (ปรับสเกลเล็กน้อยให้เห็นภาพสวยขึ้น)
    P_ad = (M + G) / (Y * 0.5)
    P_as = Cost_Shock + 0.005 * Y
    
    # 3. หาจุดสมดุล (Numerical Solution)
    idx = np.argwhere(np.diff(np.sign(P_ad - P_as))).flatten()
    
    plt.plot(Y, P_ad, label='AD', color='#1f77b4', linewidth=2.5)
    plt.plot(Y, P_as, label='AS', color='#ff7f0e', linewidth=2.5)

    # ตรวจสอบว่ามีจุดตัดหรือไม่ก่อนดึงค่า
    if len(idx) > 0:
        Y_star = Y[idx][0]
        P_star = P_ad[idx][0]
        
        plt.scatter(Y_star, P_star, color='black', s=100, zorder=5)
        plt.annotate(f'Equilibrium\nY*={Y_star:.1f}\nP*={P_star:.2f}', 
                     xy=(Y_star, P_star), xytext=(Y_star+200, P_star+2),
                     arrowprops=dict(arrowstyle='->'))
    else:
        # กรณีไม่ตัดกัน ให้แจ้งเตือนบนกราฟแทนการปล่อยให้ Error
        plt.text(500, 5, "No Equilibrium Found\nin this range", 
                 fontsize=12, color='red', ha='center', bbox=dict(facecolor='white', alpha=0.5))
        print("Warning: Curves do not intersect. Consider adjusting G, M or Cost_Shock.")

    plt.title(f"AS-AD Model: G={G}, M={M}, Shock={Cost_Shock}")
    plt.xlabel("Real GDP (Y)")
    plt.ylabel("Price Level (P)")
    plt.ylim(0, 20)
    plt.xlim(0, 2000)
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.show()
คลิกเพื่อดูโค้ดไพธอน
# --- ตัวอย่างการวิเคราะห์ ---
# กรณีปกติ
simulate_as_ad(G=500, M=1000, Cost_Shock=2)

# กรณีเกิด Stagflation (AS ลดลง/ต้นทุนสูงขึ้น เช่น วิกฤตน้ำมัน)
# simulate_as_ad(G=500, M=1000, Cost_Shock=8)

  1. ประเด็นวิเคราะห์สำหรับนักเศรษฐศาสตร์ (Policy Insight) ในบทปฏิบัติการนี้ นักศึกษาจะได้ทดลองนำ “ตัวแปรจริง” มาใส่ในแบบจำลอง:

    • Demand-Pull Inflation: หากรัฐบาลกระตุ้นเศรษฐกิจมากเกินไป (\(G\) เพิ่ม) เส้น AD จะ Shift ไปทางขวา ทำให้ \(Y\) เพิ่ม แต่จะตามมาด้วยระดับราคา \(P\) ที่สูงขึ้น

    • Cost-Push Inflation (Stagflation): หากต้นทุนการผลิตพุ่งสูงขึ้น (Cost_Shock เพิ่ม) เส้น AS จะ Shift ขึ้นด้านบน ผลลัพธ์คือระดับราคา \(P\) จะสูงขึ้นในขณะที่ผลผลิต \(Y\) ลดลง ซึ่งเป็นสภาวะที่แก้ไขได้ยากที่สุดทางการเมืองและเศรษฐกิจ