ANOVA dan Ujian Susulan
Bandingkan min merentas tiga atau lebih kumpulan dengan ANOVA sehala dan jalankan HSD Tukey untuk mengenal pasti pasangan yang berbeza.
ANOVA dan Ujian Susulan ialah pelajaran Pandas & NumPy Academy percuma di CoddyKit. Ini ialah pelajaran 4 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Pandas & NumPy Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Pandas & NumPy Academy merangkumi sejumlah 4 pelajaran.
Mengapa Bukan Ujian-T Berbilang?
Apabila membandingkan min bagi tiga kumpulan atau lebih, menjalankan berbilang ujian-t meningkatkan kadar ralat Jenis I (kadar positif palsu). Menguji kumpulan A berbanding B, A berbanding C, dan B berbanding C pada α=0.05 setiap satu menghasilkan kebarangkalian positif palsu keseluruhan kira-kira 14%, bukannya 5%. Analisis Varians (ANOVA) menyelesaikan masalah ini dengan menguji semua kumpulan secara serentak dalam satu ujian, sambil mengekalkan kadar positif palsu tepat pada α. Satu ANOVA menggantikan semua ujian-t berpasangan bagi persoalan keseluruhan: 'Adakah mana-mana kumpulan berbeza?'
ANOVA Satu Hala: Gambaran Keseluruhan
ANOVA satu hala menguji sama ada min bagi tiga kumpulan atau lebih berbeza secara signifikan. Ia menguraikan varians keseluruhan kepada varians antara kumpulan (diterangkan oleh keahlian kumpulan) dan varians dalam kumpulan (hingar rawak). Statistik-F ialah nisbah kedua-duanya: F = (varians antara kumpulan) / (varians dalam kumpulan). Nilai F yang besar bermaksud perbezaan kumpulan adalah besar berbanding hingar, lalu menghasilkan nilai-p yang kecil. Hipotesis nol ialah H₀: semua min kumpulan adalah sama.
import numpy as np
from scipy import stats
np.random.seed(0)
# Three product variants with different conversion rates
group_a = np.random.normal(10.0, 2.0, 50) # baseline
group_b = np.random.normal(11.5, 2.0, 50) # slightly better
group_c = np.random.normal(13.0, 2.0, 50) # clearly better
f_stat, p = stats.f_oneway(group_a, group_b, group_c)
print(f'F-statistic: {f_stat:.3f}')
print(f'p-value: {p:.6f}')
print('At least one group differs?', 'Yes' if p < 0.05 else 'No')ANOVA dengan DataFrames Pandas
Dalam amalan, data anda berada dalam DataFrame berformat panjang, iaitu satu lajur menyimpan label kumpulan dan satu lagi menyimpan ukuran. Ekstrak setiap kumpulan sebagai Siri dan hantarkannya kepada stats.f_oneway(). Sebagai alternatif, jika anda mempunyai DataFrame berformat lebar (satu lajur bagi setiap kumpulan), hantarkan setiap lajur secara terus. Fungsi ini menerima sebarang bilangan argumen kedudukan, jadi mudah diperluas kepada 4, 5 atau lebih kumpulan.
import pandas as pd
import numpy as np
from scipy import stats
np.random.seed(1)
df = pd.DataFrame({
'group': ['A']*40 + ['B']*40 + ['C']*40 + ['D']*40,
'score': np.concatenate([
np.random.normal(70, 10, 40),
np.random.normal(75, 10, 40),
np.random.normal(80, 10, 40),
np.random.normal(72, 10, 40)
])
})
groups = [group['score'].values
for _, group in df.groupby('group')]
f, p = stats.f_oneway(*groups)
print(f'F={f:.3f}, p={p:.4f}')
print(df.groupby('group')['score'].mean().round(2))Andaian ANOVA
ANOVA satu hala membuat andaian berikut: (1) Kebebasan — pemerhatian adalah bebas antara satu sama lain; (2) Kenormalan — baki adalah lebih kurang normal dalam setiap kumpulan (teguh untuk sampel besar melalui CLT); (3) Homoskedastisiti — varians adalah sama merentas kumpulan. Uji andaian varians dengan ujian Levene (stats.levene(*groups)). Jika varians tidak sama, gunakan ANOVA Welch sebagai ganti, yang tersedia dalam pustaka pingouin atau boleh dikira melalui statsmodels.
import numpy as np
from scipy import stats
np.random.seed(0)
g1 = np.random.normal(10, 2, 40)
g2 = np.random.normal(12, 2, 40)
g3 = np.random.normal(11, 8, 40) # Much higher variance
# Test equal variances
stat_l, p_l = stats.levene(g1, g2, g3)
print(f'Levene\'s test: stat={stat_l:.3f}, p={p_l:.4f}')
if p_l < 0.05:
print('Warning: Unequal variances! Standard ANOVA may be unreliable.')
print('Consider Welch\'s ANOVA or Kruskal-Wallis.')Kruskal-Wallis: ANOVA Bukan Parametrik
Apabila andaian ANOVA dilanggar (taburan tidak normal, sampel kecil, varians tidak sama), ujian Kruskal-Wallis ialah alternatif bukan parametrik. Ujian ini menentukan sama ada taburan kumpulan berbeza dengan menukar data kepada kedudukan dan membandingkan jumlah kedudukan. Gunakan scipy.stats.kruskal(*groups). Hipotesis nol menyatakan bahawa semua kumpulan mempunyai taburan yang sama (setara dengan menguji median yang sama apabila taburan mempunyai bentuk yang sama). Ujian ini sentiasa sah tetapi kurang berkuasa berbanding ANOVA apabila andaian dipenuhi.
import numpy as np
from scipy import stats
np.random.seed(0)
# Non-normal data: customer satisfaction scores (1-10 scale)
g1 = np.random.choice(range(1, 11), 50, p=[0.05]*10)
g2 = np.random.choice(range(1, 11), 50, p=[0.02, 0.03, 0.05, 0.08, 0.12, 0.15, 0.20, 0.15, 0.12, 0.08])
g3 = np.random.choice(range(1, 11), 50, p=[0.15, 0.15, 0.15, 0.15, 0.10, 0.10, 0.08, 0.05, 0.04, 0.03])
stat, p = stats.kruskal(g1, g2, g3)
print(f'Kruskal-Wallis: H={stat:.3f}, p={p:.4f}')
print('Groups differ?', 'Yes' if p < 0.05 else 'No')Ujian Pasca-Hoc: Sebab Anda Memerlukannya
ANOVA yang signifikan memberitahu anda bahawa sekurang-kurangnya satu min kumpulan berbeza, tetapi bukan pasangan yang mana berbeza. Ujian pasca-hoc menjalankan semua perbandingan berpasangan sambil membetulkan perbandingan berbilang. Yang paling popular ialah Perbezaan Signifikan Jujur Tukey (Tukey HSD), yang mengawal kadar ralat sekeluarga tepat pada α. Ia tersedia dalam statsmodels.stats.multicomp.pairwise_tukeyhsd(). Jalankan ujian pasca-hoc hanya selepas ANOVA yang signifikan — bukan sebagai pencarian rawak apabila keputusannya tidak signifikan.
import numpy as np
import pandas as pd
from scipy import stats
from statsmodels.stats.multicomp import pairwise_tukeyhsd
np.random.seed(0)
data = np.concatenate([
np.random.normal(70, 10, 40),
np.random.normal(80, 10, 40),
np.random.normal(75, 10, 40)
])
groups = ['A']*40 + ['B']*40 + ['C']*40
# First confirm ANOVA is significant
f, p = stats.f_oneway(*[data[i*40:(i+1)*40] for i in range(3)])
print(f'ANOVA p={p:.4f}')
if p < 0.05:
print('Post-hoc Tukey HSD:')
print(pairwise_tukeyhsd(data, groups, alpha=0.05))Membaca Output Tukey HSD
Jadual Tukey HSD mempunyai satu baris bagi setiap pasangan kumpulan. Lajur yang perlu diberi perhatian ialah: meandiff (perbezaan min antara pasangan), lower dan upper (selang keyakinan 95% bagi perbezaan), serta reject (True jika pasangan berbeza secara signifikan pada α). Selang keyakinan yang tidak merangkumi sifar bermaksud pasangan tersebut berbeza secara signifikan. Kumpulan yang selang keyakinannya bertindih tidak berbeza secara signifikan antara satu sama lain.
import numpy as np
from statsmodels.stats.multicomp import pairwise_tukeyhsd
np.random.seed(42)
data = np.concatenate([
np.random.normal(10, 2, 60), # Group A
np.random.normal(13, 2, 60), # Group B (clearly higher)
np.random.normal(10.5, 2, 60) # Group C (barely different from A)
])
groups = ['A']*60 + ['B']*60 + ['C']*60
result = pairwise_tukeyhsd(data, groups, alpha=0.05)
print(result)
# A-B: reject=True (B is higher)
# A-C: reject=False (barely different)
# B-C: reject=True (B is higher)Pembetulan Bonferroni dan Benjamini-Hochberg
Sebagai alternatif kepada Tukey HSD, anda boleh menggunakan pembetulan Bonferroni pada ujian-t berpasangan: jalankan semua ujian-t, kemudian laraskan ambang kepada α/k, dengan k ialah bilangan perbandingan. Kaedah ini konservatif — perbezaan sebenar mungkin terlepas. Pembetulan Kadar Penemuan Palsu (FDR) Benjamini-Hochberg kurang konservatif: ia mengawal perkadaran jangkaan penemuan palsu, lalu membenarkan lebih banyak positif benar dengan kos sedikit lebih banyak positif palsu. Gunakan statsmodels.stats.multitest.multipletests(p_values, method='fdr_bh').
import numpy as np
from scipy import stats
from statsmodels.stats.multitest import multipletests
np.random.seed(0)
groups = [np.random.normal(10 + i*1.5, 2, 40) for i in range(4)]
names = ['A', 'B', 'C', 'D']
# All pairwise t-tests
p_values = []
pairs = []
for i in range(len(groups)):
for j in range(i+1, len(groups)):
_, p = stats.ttest_ind(groups[i], groups[j])
p_values.append(p)
pairs.append(f'{names[i]}-{names[j]}')
# Benjamini-Hochberg correction
reject, adj_p, _, _ = multipletests(p_values, method='fdr_bh')
for pair, p, ap, r in zip(pairs, p_values, adj_p, reject):
print(f'{pair}: raw_p={p:.4f}, adj_p={ap:.4f}, significant={r}')Saiz Kesan untuk ANOVA: Eta Kuasa Dua
Bagi ANOVA, ukuran yang sepadan dengan d Cohen ialah eta kuasa dua (η²): perkadaran varians keseluruhan yang diterangkan oleh keahlian kumpulan. η² = SS_between / SS_total. Nilai: < 0.01 adalah kecil, 0.06 adalah sederhana, > 0.14 adalah besar. Eta kuasa dua separa (η²_p) lebih lazim dalam penyelidikan yang diterbitkan: ia membahagi dengan varians kumpulan ditambah varians ralat sahaja, bukan jumlah keseluruhan. Sentiasa kira η² bersama nilai-p ANOVA untuk menunjukkan sama ada kesan itu bermakna secara praktikal, bukan sekadar dapat dikesan secara statistik.
import numpy as np
from scipy import stats
np.random.seed(0)
groups = [
np.random.normal(10, 2, 50),
np.random.normal(12, 2, 50),
np.random.normal(14, 2, 50)
]
all_data = np.concatenate(groups)
grand_mean = all_data.mean()
ss_between = sum(len(g) * (g.mean() - grand_mean)**2 for g in groups)
ss_total = sum((x - grand_mean)**2 for g in groups for x in g)
eta_sq = ss_between / ss_total
f, p = stats.f_oneway(*groups)
print(f'F={f:.3f}, p={p:.4f}')
print(f'Eta-squared: {eta_sq:.4f} ({eta_sq:.1%} of variance explained)')Gambaran Keseluruhan ANOVA Dua Hala
ANOVA dua hala memperluas ANOVA satu hala kepada dua faktor kategori secara serentak. Contohnya, menguji sama ada markah peperiksaan berbeza berdasarkan kaedah pengajaran dan tahap pengalaman pelajar secara serentak. Ia juga menguji kesan interaksi: adakah kesan kaedah pengajaran bergantung pada tahap pengalaman? ANOVA dua hala dilaksanakan dalam statsmodels melalui ols('score ~ C(method) + C(level) + C(method):C(level)', data=df).fit() dan anova_lm(model). Ini menjadi asas bagi reka bentuk eksperimen yang lebih lanjut.
import pandas as pd
import numpy as np
from statsmodels.formula.api import ols
from statsmodels.stats.anova import anova_lm
np.random.seed(0)
df = pd.DataFrame({
'method': ['trad']*60 + ['active']*60,
'level': ['beginner']*30 + ['advanced']*30 + ['beginner']*30 + ['advanced']*30,
'score': (np.random.normal(70, 8, 30).tolist() +
np.random.normal(80, 8, 30).tolist() +
np.random.normal(75, 8, 30).tolist() +
np.random.normal(88, 8, 30).tolist())
})
model = ols('score ~ C(method) + C(level) + C(method):C(level)', data=df).fit()
print(anova_lm(model, typ=2)[['F', 'PR(>F)']].round(4))ANOVA Ukuran Berulang
ANOVA ukuran berulang digunakan apabila subjek yang sama diukur beberapa kali — contohnya, menguji masa tindak balas pada titik masa 0, 30 dan 60 minit selepas rawatan. Ia ialah generalisasi berbilang kumpulan bagi ujian-t berpasangan. Dengan mengambil kira perbezaan individu, kaedah ini lebih berkuasa berbanding ANOVA satu hala. Dalam Python, gunakan pingouin.rm_anova() atau pg.pairwise_tests() untuk analisis pasca-hoc. Apabila sferisiti dilanggar (diuji dengan ujian Mauchly), gunakan nilai-p yang dibetulkan Greenhouse-Geisser.
import pandas as pd
import numpy as np
# Example structure for repeated measures (pingouin library)
np.random.seed(0)
subjects = list(range(20)) * 3 # 20 subjects, 3 time points
timepoints = ['T0']*20 + ['T1']*20 + ['T2']*20
scores = np.concatenate([
np.random.normal(50, 10, 20), # baseline
np.random.normal(55, 10, 20), # improved
np.random.normal(60, 10, 20) # further improved
])
df_rm = pd.DataFrame({'subject': subjects, 'time': timepoints, 'score': scores})
print(df_rm.groupby('time')['score'].mean().round(2))
# Use pingouin.rm_anova(data=df_rm, dv='score', within='time', subject='subject')Semakan Pantas
Uji pemahaman anda tentang konsep Analisis Data daripada pelajaran ini.
Ulang Kaji Pelajaran
Dalam pelajaran ini, anda telah mempelajari bahawa: scipy.stats.f_oneway() menguji sama ada mana-mana kumpulan berbeza dari segi min sambil mengawal kadar ralat Jenis I keseluruhan, ujian pasca-hoc (Tukey HSD) mengenal pasti pasangan tertentu yang berbeza selepas ANOVA yang signifikan, dan Kruskal-Wallis ialah pilihan bukan parametrik apabila andaian kenormalan atau varians sama dilanggar. Seterusnya kita akan memulakan projek kemuncak yang menggabungkan semua kemahiran ke dalam saluran data hujung ke hujung.
Pelajari Python dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 30
- Pelajaran
- 120
Soalan Lazim
Adakah pelajaran “ANOVA dan Ujian Susulan” percuma?
Ya — teks penuh “ANOVA dan Ujian Susulan” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Pandas & NumPy Academy, tingkat taraf kepada CoddyKit PRO. Kursus Pandas & NumPy Academy merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “ANOVA dan Ujian Susulan”?
Bandingkan min merentas tiga atau lebih kumpulan dengan ANOVA sehala dan jalankan HSD Tukey untuk mengenal pasti pasangan yang berbeza. Anda berlatih Pandas & NumPy Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Pandas & NumPy Academy?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Pandas & NumPy Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 4 daripada 4.
Berapa lamakah pelajaran “ANOVA dan Ujian Susulan” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Pandas & NumPy Academy ini?
Ya. Setiap pelajaran Pandas & NumPy Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Statistik Deskriptif dan Pengujian Kenormalan
- Ujian-t untuk Membandingkan Min
- Ujian Khi Kuasa Dua untuk Kebebasan
- ANOVA dan Ujian Susulan