สัปดาห์ที่ 09 · Data with AI

NumPy + Matplotlib — คำนวณและเห็นข้อมูล

ตาราง (W08) เก็บข้อมูลได้ · NumPy คำนวณ ได้เร็ว · Matplotlib ทำให้เรา "เห็น" ได้ · 2 library นี้คือเครื่องมือมาตรฐานของวิศวกรในยุค Python

เป้าหมายสัปดาห์นี้

🧮 NumPy — array แทน list สำหรับงานคำนวณ

import numpy as np

# สร้าง array
scores = np.array([85, 72, 91, 60, 45, 78, 88])

# operation แบบ vectorized — ทั้ง array ทีเดียว
scores * 2              # [170, 144, 182, 120, 90, 156, 176]
scores + 5              # [90, 77, 96, 65, 50, 83, 93]
scores >= 50            # [True, True, True, True, False, True, True]
scores[scores >= 50]    # [85, 72, 91, 60, 78, 88]

# สถิติ
scores.mean()           # ค่าเฉลี่ย
scores.std()            # ส่วนเบี่ยงเบนมาตรฐาน
scores.min()            # ต่ำสุด
scores.max()            # สูงสุด
scores.sum()            # ผลรวม
np.median(scores)       # ค่ามัธยฐาน
np.percentile(scores, 75)  # quartile ที่ 3

ทำไม NumPy เร็วกว่า list

# Python list — วน 1 ล้านครั้ง
nums = list(range(1_000_000))
doubled = []
for n in nums:
    doubled.append(n * 2)
# ~50 ms

# NumPy
nums = np.arange(1_000_000)
doubled = nums * 2
# ~2 ms — เร็วกว่า 20 เท่า

เคล็ดลับ: NumPy เก็บข้อมูลเป็น C array · ไม่ใช่ object · ทำงานทีเดียวทั้งก้อน

🏗️ สร้าง array แบบต่าง ๆ

np.array([1, 2, 3])           # จาก list
np.zeros(5)                    # [0, 0, 0, 0, 0]
np.ones(5)                     # [1, 1, 1, 1, 1]
np.arange(0, 10, 2)            # [0, 2, 4, 6, 8]
np.linspace(0, 1, 5)           # 5 ค่าจาก 0 ถึง 1: [0, 0.25, 0.5, 0.75, 1]

# 2D
matrix = np.array([
    [1, 2, 3],
    [4, 5, 6],
])
matrix.shape   # (2, 3) — 2 rows, 3 cols
matrix[0, 1]   # 2 — row 0, col 1
matrix[:, 0]   # column 0: [1, 4]
matrix[0, :]   # row 0: [1, 2, 3]

📐 ตัวอย่างวิศวกรรม — คำนวณแรงดันไฟฟ้า

import numpy as np

# เวลา (วินาที) — 1000 จุด ตั้งแต่ 0 ถึง 0.05
t = np.linspace(0, 0.05, 1000)

# สัญญาณ sinusoidal 50 Hz
V = 220 * np.sin(2 * np.pi * 50 * t)

# คำนวณ
V_rms = np.sqrt(np.mean(V**2))   # RMS = 220/sqrt(2) ≈ 155.6
V_peak = V.max()
print(f"V_rms = {V_rms:.2f} V")
print(f"V_peak = {V_peak:.2f} V")

📊 Matplotlib — กราฟ 5 ชนิด

1. Line plot — สำหรับ "time series" หรือ "x ↔ y ต่อเนื่อง"

import matplotlib.pyplot as plt

t = np.linspace(0, 0.05, 1000)
V = 220 * np.sin(2 * np.pi * 50 * t)

plt.figure(figsize=(10, 4))
plt.plot(t, V, label="220V 50Hz")
plt.xlabel("Time (s)")
plt.ylabel("Voltage (V)")
plt.title("AC Power Signal")
plt.legend()
plt.grid(True)
plt.show()

2. Scatter plot — ดู "ความสัมพันธ์ระหว่าง 2 ตัวแปร"

study_hours = [2, 5, 8, 3, 10, 6, 4, 12, 7, 9]
exam_score = [55, 70, 85, 60, 92, 78, 65, 95, 80, 88]

plt.scatter(study_hours, exam_score)
plt.xlabel("ชั่วโมงทบทวน")
plt.ylabel("คะแนนสอบ")
plt.title("Study Time vs Exam Score")
plt.grid(True)
plt.show()

3. Bar chart — เปรียบเทียบ "กลุ่ม"

subjects = ["Math", "Physics", "CP", "Lab", "Eng"]
avg_scores = [75, 68, 82, 88, 70]

plt.bar(subjects, avg_scores, color="#3776ab")
plt.ylabel("คะแนนเฉลี่ย")
plt.title("คะแนนเฉลี่ยแต่ละวิชา")
plt.show()

4. Histogram — ดู "การกระจาย" ของข้อมูล 1 ตัวแปร

# คะแนนของนักศึกษา 100 คน
scores = np.random.normal(70, 12, 100)  # mean=70, std=12

plt.hist(scores, bins=15, color="#ffd43b", edgecolor="black")
plt.xlabel("คะแนน")
plt.ylabel("จำนวนนักศึกษา")
plt.title("การกระจายคะแนนสอบ")
plt.show()

5. Box plot — เปรียบเทียบ "การกระจาย" หลายกลุ่ม

year1 = np.random.normal(65, 10, 30)
year2 = np.random.normal(72, 8, 30)
year3 = np.random.normal(78, 7, 30)

plt.boxplot([year1, year2, year3], labels=["Year 1", "Year 2", "Year 3"])
plt.ylabel("คะแนน")
plt.title("กระจายคะแนนแต่ละชั้นปี")
plt.show()

🎯 เลือกกราฟแบบไหน?

คำถามกราฟ
ค่าเปลี่ยนตามเวลา / x ต่อเนื่องline
ดูความสัมพันธ์ 2 ตัวแปรscatter
เปรียบเทียบกลุ่ม (categorical)bar
ดูการกระจายของ 1 ตัวแปรhistogram
เปรียบเทียบกระจายของหลายกลุ่มbox plot
สัดส่วน (รวมเป็น 100%)pie (ใช้ระวัง — อ่านยาก)
เปลี่ยนแปลงสะสมarea
หลีกเลี่ยง pie chart — มนุษย์อ่านมุมยากกว่าความยาว · ใช้ bar chart แทนแทบทุกครั้ง · ยกเว้นข้อมูล 2-3 กลุ่ม

✨ ทำกราฟให้ "อ่านง่าย"

plt.figure(figsize=(10, 5))                        # ขนาด
plt.plot(t, V, label="V(t)", linewidth=2)          # เส้นหนา
plt.xlabel("Time (s)", fontsize=12)                # axis label
plt.ylabel("Voltage (V)", fontsize=12)
plt.title("AC Power 50 Hz", fontsize=14, fontweight="bold")
plt.legend(loc="upper right")                      # ตำแหน่ง legend
plt.grid(True, alpha=0.3)                          # grid อ่อน ๆ
plt.axhline(0, color="black", linewidth=0.5)       # เส้นแกน
plt.tight_layout()                                 # padding
plt.savefig("ac_signal.png", dpi=150)              # เซฟเป็นรูป
plt.show()

กฎ "ทุกกราฟต้องมี"

  1. Title — บอกว่าเป็นกราฟอะไร
  2. X / Y label พร้อมหน่วย
  3. Legend ถ้ามีหลายเส้น
  4. Grid (สำหรับอ่านค่า)

🖼️ Subplots — หลายกราฟใน figure เดียว

fig, axes = plt.subplots(1, 2, figsize=(12, 4))

axes[0].plot(t, V)
axes[0].set_title("Voltage")
axes[0].set_xlabel("Time (s)")

axes[1].plot(t, V**2 / 100)  # power
axes[1].set_title("Power")
axes[1].set_xlabel("Time (s)")

plt.tight_layout()
plt.show()

🤖 ใช้ AI ช่วยทำกราฟ — เคล็ดลับ

🧪 Workshop — Visualize ข้อมูลของตัวเอง

  1. ใช้ CSV จาก W08 — เปิดใน Jupyter/Colab notebook ใหม่
  2. คำนวณสถิติ 5 ตัว — mean, std, min, max, median ของ column ที่เป็น numeric
  3. วาดกราฟ 4 ชนิด — line, scatter, bar, histogram ของข้อมูลในชุดเดียวกัน
  4. ใส่ title, axis label, legend ครบ
  5. เซฟกราฟเป็น .png 4 ไฟล์plt.savefig(..., dpi=150)
  6. เขียน "Story" ใต้แต่ละกราฟ — 2-3 ประโยคว่าเห็นอะไรจากกราฟ
  7. ถาม AI ว่ายังขาดกราฟอะไร — paste preview ของ DataFrame + กราฟที่ทำแล้ว → ขอ AI แนะนำกราฟที่ 5

ข้อผิดที่พบบ่อย

ลืม importimport numpy as np + import matplotlib.pyplot as plt เป็น 2 บรรทัดที่ต้องมีทุก notebook
ใช้ Python list ใน NumPy operation — เช่น my_list * 2 = ทำ list ซ้ำ 2 ครั้ง ไม่ใช่ คูณ 2 · ต้องแปลงเป็น array ก่อน
กราฟไม่มี title / axis label — ทำให้คน (และ AI) อ่านไม่ออกว่ากำลังดูอะไร · ตรวจสอบทุกกราฟก่อนเซฟ
ใช้ pie chart 7 ชิ้น — อ่านยาก · ใช้ bar chart เรียงจากใหญ่ไปเล็กแทน

ส่งงานสัปดาห์นี้

Reference จาก slide เดิม

ครอบคลุม Topic 8 — NumPy และส่วน Matplotlib ของ Topic 9 — OOP and Matplotlib