0Pricing
Pandas & NumPy Academy · บทเรียน

การทดสอบทีเพื่อเปรียบเทียบค่าเฉลี่ย

ดำเนินการทดสอบทีแบบกลุ่มตัวอย่างเดียว แบบสองกลุ่มอิสระ และแบบจับคู่ด้วย scipy.stats พร้อมแปลความหมายช่วงความเชื่อมั่น

การทดสอบทีเพื่อเปรียบเทียบค่าเฉลี่ย เป็นบทเรียน Pandas & NumPy Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Pandas & NumPy Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน

t-test คืออะไร

t-test คือการทดสอบสมมติฐานที่ใช้พิจารณาว่าความแตกต่างของค่าเฉลี่ยระหว่างกลุ่มมีนัยสำคัญทางสถิติหรือมีแนวโน้มเกิดจากความบังเอิญแบบสุ่ม โดยเปรียบเทียบความแตกต่างที่สังเกตได้กับความแปรปรวนในข้อมูล แล้วคำนวณเป็นสถิติ tและค่า p หาก p ≤ 0.05 (เกณฑ์มาตรฐานที่ใช้โดยทั่วไป) เราจะปฏิเสธสมมติฐานศูนย์ที่ว่าค่าเฉลี่ยเท่ากัน t-test ที่ใช้กันทั่วไปมีสามประเภท ได้แก่ แบบหนึ่งตัวอย่าง แบบสองตัวอย่างอิสระ และ แบบจับคู่ โดยแต่ละประเภทเหมาะกับการออกแบบการทดลองที่แตกต่างกัน

t-test แบบหนึ่งตัวอย่าง

t-test แบบหนึ่งตัวอย่างใช้ตรวจสอบว่าค่าเฉลี่ยของตัวอย่างแตกต่างอย่างมีนัยสำคัญจากค่าเฉลี่ยของประชากรที่ทราบหรือกำหนดเป็นสมมติฐานหรือไม่ ตัวอย่างเช่น “เวลาเฉลี่ยในการจัดส่งของเราแตกต่างจากมาตรฐานอุตสาหกรรมที่ 3 วันอย่างมีนัยสำคัญหรือไม่” ใช้ scipy.stats.ttest_1samp(data, popmean) สมมติฐานศูนย์คือ H₀: mean = popmean ค่า p ขนาดเล็กทำให้คุณปฏิเสธ H₀ และสรุปได้ว่าค่าเฉลี่ยของตัวอย่างแตกต่างจากค่าที่เป็นเป้าหมาย

import numpy as np
from scipy import stats

np.random.seed(42)
# Delivery times in days (true mean is ~3.5, not 3)
delivery_times = np.random.normal(loc=3.5, scale=0.8, size=50)

# Test: is our mean significantly different from 3 days?
stat, p = stats.ttest_1samp(delivery_times, popmean=3.0)
print(f'Sample mean: {delivery_times.mean():.3f}')
print(f't-statistic: {stat:.3f}')
print(f'p-value: {p:.4f}')
print('Differs from 3?', 'Yes' if p < 0.05 else 'No')

t-test แบบสองตัวอย่างอิสระ

การทดสอบ t สำหรับสองกลุ่มตัวอย่างอิสระใช้เปรียบเทียบค่าเฉลี่ยของกลุ่มอิสระสองกลุ่ม ตัวอย่างเช่น “ตัวแปรในการทดสอบ A/B สร้างรายได้เฉลี่ยสูงกว่ากลุ่มควบคุมหรือไม่” ให้ใช้ scipy.stats.ttest_ind(group_a, group_b) พารามิเตอร์ equal_var มีความสำคัญ: ให้กำหนด equal_var=False (การทดสอบ t ของ Welch) เมื่อทั้งสองกลุ่มอาจมีความแปรปรวนแตกต่างกัน ซึ่งเป็นค่าเริ่มต้นที่ปลอดภัยสำหรับข้อมูลจริงส่วนใหญ่

import numpy as np
from scipy import stats

np.random.seed(0)
# A/B test revenue per session
control = np.random.normal(loc=25.0, scale=8.0, size=80)
variant = np.random.normal(loc=28.0, scale=9.0, size=80)

# Welch's t-test (does not assume equal variances)
stat, p = stats.ttest_ind(control, variant, equal_var=False)
print(f'Control mean: {control.mean():.2f}')
print(f'Variant mean: {variant.mean():.2f}')
print(f't-statistic: {stat:.3f}')
print(f'p-value: {p:.4f}')
print('Significant difference?', 'Yes' if p < 0.05 else 'No')

การทดสอบทางเดียวเทียบกับการทดสอบสองทาง

โดยค่าเริ่มต้น การทดสอบ t เป็นการทดสอบสองทาง กล่าวคือ ทดสอบว่าค่าเฉลี่ยแตกต่างกันในทิศทางใดทิศทางหนึ่งหรือไม่ (มากกว่า OR น้อยกว่า) หากคุณมีสมมติฐานที่ระบุทิศทาง (“ตัวแปรเพิ่มรายได้”) ให้ใช้การทดสอบทางเดียวร่วมกับพารามิเตอร์ alternative: 'greater' หรือ 'less' การทดสอบทางเดียวมีพลังทางสถิติมากกว่าสำหรับทิศทางที่ระบุ แต่ไม่ให้หลักฐานเกี่ยวกับอีกทิศทางหนึ่ง ควรกำหนดทิศทางไว้ก่อนดูข้อมูล เพื่อหลีกเลี่ยง HARKing (การตั้งสมมติฐานหลังทราบผลลัพธ์แล้ว)

import numpy as np
from scipy import stats

np.random.seed(1)
control = np.random.normal(25, 8, 100)
variant = np.random.normal(27, 8, 100)

# Two-tailed (default): does mean differ at all?
stat, p_two = stats.ttest_ind(control, variant, equal_var=False,
                              alternative='two-sided')
# One-tailed: is variant > control?
stat, p_one = stats.ttest_ind(control, variant, equal_var=False,
                              alternative='less')

print(f'Two-tailed p: {p_two:.4f}')
print(f'One-tailed p (variant greater): {p_one:.4f}')

การทดสอบ t แบบจับคู่

การทดสอบ t แบบจับคู่ใช้เมื่อข้อมูลสังเกตแต่ละรายการในกลุ่ม A มีคู่ที่สอดคล้องกันตามธรรมชาติในกลุ่ม B ตัวอย่างเช่น การวัดก่อนและหลังการรักษาในคนกลุ่มเดิม หรือร้านค้าเดิมในสองเดือนที่แตกต่างกัน การจับคู่ช่วยควบคุมความแปรปรวนระหว่างหน่วยตัวอย่าง ทำให้การทดสอบมีพลังมากกว่าการทดสอบ t สำหรับกลุ่มอิสระเมื่อใช้ข้อมูลชุดเดียวกัน ให้ใช้ scipy.stats.ttest_rel(before, after) ลำดับของสมาชิกต้องจับคู่กัน: before[i] และ after[i] ต้องมาจากหน่วยตัวอย่างเดียวกัน

import numpy as np
from scipy import stats

np.random.seed(5)
# Blood pressure before and after medication (paired)
before = np.random.normal(130, 10, 30)
after = before - np.random.normal(5, 3, 30)  # Treatment reduces BP by ~5

stat, p = stats.ttest_rel(before, after)
print(f'Mean before: {before.mean():.2f}')
print(f'Mean after: {after.mean():.2f}')
print(f't-statistic: {stat:.3f}')
print(f'p-value: {p:.4f}')
print('Treatment effective?', 'Yes' if p < 0.05 else 'No')

การตีความค่าสถิติ t

ค่าสถิติ tวัดว่าความแตกต่างที่สังเกตได้อยู่ห่างจากศูนย์กี่ค่าความคลาดเคลื่อนมาตรฐาน ค่าสถิติ t เท่ากับ 2 หมายความว่าความแตกต่างที่สังเกตได้สูงกว่าสิ่งที่คาดว่าจะเกิดภายใต้สมมติฐานว่างอยู่ 2 ค่าความคลาดเคลื่อนมาตรฐาน สำหรับการทดสอบสองทางที่ α=0.05 และมีตัวอย่างขนาดใหญ่ ค่าวิกฤตมีค่าประมาณ ±1.96 ดังนั้น |t| > 1.96 จึงให้ค่า p < 0.05 ค่า p แปลงค่าสถิติ t เป็นความน่าจะเป็น ทำให้ตีความได้ง่ายขึ้นโดยไม่ต้องเปิดตารางการแจกแจง t

import numpy as np
from scipy import stats

# Demonstrate relationship between t-statistic and p-value
for t_val in [1.0, 1.96, 2.5, 3.0, 4.0]:
    # degrees of freedom = large sample -> t ~ normal
    p = 2 * stats.t.sf(abs(t_val), df=100)  # two-tailed
    print(f't = {t_val:4.2f} -> p = {p:.4f} '
          f'({'significant' if p < 0.05 else 'not significant'})')

ช่วงความเชื่อมั่นสำหรับความแตกต่างของค่าเฉลี่ย

ค่า p เพียงอย่างเดียวไม่ได้บอกขนาดของผลลัพธ์ ควรคำนวณช่วงความเชื่อมั่นสำหรับความแตกต่างของค่าเฉลี่ยเสมอ ช่วงความเชื่อมั่น 95% ที่ครอบคลุมศูนย์สอดคล้องกับ p > 0.05 (ไม่มีนัยสำคัญ) ส่วนช่วงที่ไม่ครอบคลุมศูนย์หมายความว่าความแตกต่างมีนัยสำคัญ ช่วงความเชื่อมั่นยังบอกได้ว่าขนาดผลลัพธ์มีความหมายในทางปฏิบัติหรือไม่ เช่น ความแตกต่างของรายได้ $0.01 ที่มีนัยสำคัญทางสถิติอาจไม่สำคัญ ขณะที่ความแตกต่าง $50 ที่มีค่า p=0.06 ก็อาจยังมีความสำคัญต่อธุรกิจ

import numpy as np
from scipy import stats

np.random.seed(0)
control = np.random.normal(25, 8, 80)
variant = np.random.normal(28, 8, 80)

diff = variant.mean() - control.mean()
se = np.sqrt(control.var()/len(control) + variant.var()/len(variant))
df = len(control) + len(variant) - 2
t_crit = stats.t.ppf(0.975, df=df)
ci_low = diff - t_crit * se
ci_high = diff + t_crit * se

print(f'Mean difference: {diff:.2f}')
print(f'95% CI: [{ci_low:.2f}, {ci_high:.2f}]')
print('CI excludes zero:', ci_low > 0 or ci_high < 0)

ขนาดผลลัพธ์: d ของโคเฮน

นัยสำคัญทางสถิติขึ้นอยู่กับขนาดตัวอย่าง เมื่อมีตัวอย่างมากพอ แม้แต่ความแตกต่างเพียงเล็กน้อยก็อาจมีนัยสำคัญได้ d ของโคเฮนใช้วัดนัยสำคัญในทางปฏิบัติ (ขนาดผลลัพธ์) โดยคำนวณจากความแตกต่างของค่าเฉลี่ยหารด้วยส่วนเบี่ยงเบนมาตรฐานรวม แนวทางทั่วไปคือ d < 0.2 ถือว่าเล็กน้อยมาก, 0.2–0.5 ถือว่าเล็ก, 0.5–0.8 ถือว่าปานกลาง และ > 0.8 ถือว่าใหญ่ ควรรายงานขนาดผลลัพธ์ควบคู่กับค่า p เสมอ เพราะค่า p ที่มีนัยสำคัญร่วมกับ d = 0.05 หมายความว่าความแตกต่างมีอยู่จริง แต่โดยทั่วไปอาจไม่มีความหมายในทางปฏิบัติ

import numpy as np
from scipy import stats

np.random.seed(0)
g1 = np.random.normal(25, 8, 200)
g2 = np.random.normal(28, 8, 200)

stat, p = stats.ttest_ind(g1, g2)

# Cohen's d
pooled_std = np.sqrt((g1.var() + g2.var()) / 2)
cohens_d = (g2.mean() - g1.mean()) / pooled_std

print(f'p-value: {p:.4f}')
print(f'Cohen\'s d: {cohens_d:.3f}')

if cohens_d < 0.2: print('Effect: negligible')
elif cohens_d < 0.5: print('Effect: small')
elif cohens_d < 0.8: print('Effect: medium')
else: print('Effect: large')

สมมติฐานของการทดสอบ t

การทดสอบ t สำหรับกลุ่มอิสระมีสมมติฐานดังนี้: (1) ความเป็นอิสระ — ข้อมูลสังเกตภายในแต่ละกลุ่มเป็นอิสระต่อกัน (2) การแจกแจงปกติ — ข้อมูลในแต่ละกลุ่มมีการแจกแจงใกล้เคียง normal (มีความทนทานเมื่อ n > 30 ตาม CLT) (3) สำหรับการทดสอบ t ของ Student (equal_var=True) ต้องมีความแปรปรวนเท่ากัน การทดสอบ t ของ Welch (equal_var=False) ผ่อนคลายสมมติฐานข้อ 3 และเป็นตัวเลือกที่ควรใช้มากกว่า เมื่อสมมติฐานการแจกแจงปกติถูกละเมิดอย่างรุนแรงในตัวอย่างขนาดเล็ก (< 30) ให้ใช้การทดสอบ U ของ Mann-Whitney แทน

import numpy as np
from scipy import stats

np.random.seed(0)
g1 = np.random.normal(10, 2, 30)
g2 = np.random.normal(11, 5, 30)  # Very different variance!

# Levene test for equal variances
stat_l, p_l = stats.levene(g1, g2)
print(f'Levene test p: {p_l:.4f}')
if p_l < 0.05:
    print('Unequal variances -> use Welch\'s (equal_var=False)')
    stat, p = stats.ttest_ind(g1, g2, equal_var=False)
else:
    print('Equal variances OK -> Student\'s t-test')
    stat, p = stats.ttest_ind(g1, g2, equal_var=True)
print(f'Result: t={stat:.3f}, p={p:.4f}')

การทดสอบ t กับอนุกรมของ Pandas

ในทางปฏิบัติ ข้อมูลที่คุณต้องการทดสอบมักอยู่ในคอลัมน์ของ Pandas DataFrame คุณสามารถส่งอนุกรมของ Pandas ให้ฟังก์ชันใน scipy.stats ได้โดยตรง ฟังก์ชันเหล่านี้ทำงานร่วมกับอนุกรมและอาร์เรย์ของ NumPy ได้อย่างราบรื่น ขั้นตอนทั่วไปคือ กรอง DataFrame เพื่อดึงอนุกรมของแต่ละกลุ่ม เรียกใช้การทดสอบ t แล้วเก็บผลลัพธ์ไว้ใน DataFrame สรุป รูปแบบนี้ขยายไปใช้ทดสอบคู่คอลัมน์หรือกลุ่มจำนวนมากภายในลูปได้

import pandas as pd
import numpy as np
from scipy import stats

np.random.seed(0)
df = pd.DataFrame({
    'group': ['A']*60 + ['B']*60,
    'revenue': np.concatenate([
        np.random.normal(100, 20, 60),
        np.random.normal(110, 22, 60)
    ])
})

grp_a = df.loc[df['group'] == 'A', 'revenue']
grp_b = df.loc[df['group'] == 'B', 'revenue']

stat, p = stats.ttest_ind(grp_a, grp_b, equal_var=False)
print(f'A mean: {grp_a.mean():.2f}, B mean: {grp_b.mean():.2f}')
print(f'p-value: {p:.4f}')

ปัญหาการเปรียบเทียบหลายครั้ง

การทำการทดสอบ t หลายครั้งพร้อมกันทำให้โอกาสเกิดผลบวกลวงเพิ่มขึ้น หากทำการทดสอบ t 20 ครั้งที่ α=0.05 คุณคาดว่าจะพบผลบวกลวง 1 ครั้งโดยบังเอิญ นี่คือปัญหาการเปรียบเทียบหลายครั้ง ให้ใช้การปรับแก้แบบ Bonferroni โดยหาร α ด้วยจำนวนการทดสอบ (p_threshold = 0.05 / n_tests) หากต้องการพลังทางสถิติมากขึ้นและไม่เข้มงวดจนเกินไป ให้ใช้การปรับแก้อัตราการค้นพบผลบวกลวงของ Benjamini-Hochberg (FDR) ซึ่งมีอยู่ใน statsmodels ควรปรับแก้สำหรับการเปรียบเทียบหลายครั้งเสมอเมื่อทำการทดสอบ A/B ที่มีตัวชี้วัดจำนวนมาก

import numpy as np
from scipy import stats

np.random.seed(0)
n_tests = 10
results = []
for i in range(n_tests):
    g1 = np.random.normal(0, 1, 50)
    g2 = np.random.normal(0.1, 1, 50)  # Tiny true effect
    _, p = stats.ttest_ind(g1, g2)
    results.append(p)

print('p-values:', [round(p, 3) for p in results])
bonferroni_thresh = 0.05 / n_tests
print(f'Bonferroni threshold: {bonferroni_thresh}')
print('Significant after Bonferroni:', sum(p < bonferroni_thresh for p in results))

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจแนวคิดการวิเคราะห์ข้อมูลจากบทเรียนนี้

สรุปบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า ttest_1sampใช้ทดสอบค่าเฉลี่ยของตัวอย่างเทียบกับค่าอ้างอิง, ttest_ind (การทดสอบของ Welch เมื่อ equal_var=False) ใช้เปรียบเทียบกลุ่มอิสระสองกลุ่ม และ ttest_relใช้จัดการกับการวัดแบบจับคู่ ควรรายงานd ของโคเฮนควบคู่กับค่า p เสมอ เพื่อแยกนัยสำคัญทางสถิติออกจากนัยสำคัญในทางปฏิบัติ บทถัดไป เราจะทดสอบความสัมพันธ์ระหว่างตัวแปรเชิงหมวดหมู่ด้วยการทดสอบไคสแควร์

คำถามที่พบบ่อย

บทเรียน “การทดสอบทีเพื่อเปรียบเทียบค่าเฉลี่ย” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การทดสอบทีเพื่อเปรียบเทียบค่าเฉลี่ย” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Pandas & NumPy Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การทดสอบทีเพื่อเปรียบเทียบค่าเฉลี่ย”

ดำเนินการทดสอบทีแบบกลุ่มตัวอย่างเดียว แบบสองกลุ่มอิสระ และแบบจับคู่ด้วย scipy.stats พร้อมแปลความหมายช่วงความเชื่อมั่น คุณปฏิบัติ Pandas & NumPy Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Pandas & NumPy Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Pandas & NumPy Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “การทดสอบทีเพื่อเปรียบเทียบค่าเฉลี่ย” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Pandas & NumPy Academy นี้ได้ไหม

ได้ บทเรียน Pandas & NumPy Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. สถิติเชิงพรรณนาและการทดสอบการแจกแจงปกติ
  2. การทดสอบทีเพื่อเปรียบเทียบค่าเฉลี่ย
  3. การทดสอบไคสแควร์เพื่อความเป็นอิสระ
  4. ANOVA และการทดสอบภายหลัง
← กลับไปที่ Pandas & NumPy Academy