Pandas & NumPy Academy · درس

اختبارات t لمقارنة المتوسطات

أجرِ اختبارات t لعينة واحدة، ولعينتين مستقلتين، ولعينتين مترابطتين باستخدام scipy.stats، وفسّر فواصل الثقة

الدرس 2 من 413 خطوة

اختبارات t لمقارنة المتوسطات درس مجاني في Pandas & NumPy Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Pandas & NumPy Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Pandas & NumPy Academy 4 دروس في المجموع.

ما اختبار T؟

اختبار t هو اختبار فرضيات يحدد ما إذا كان الفرق بين متوسطات المجموعات مهمًا إحصائيًا أو يُرجح أن يكون ناتجًا عن الصدفة العشوائية. فهو يقارن الفرق الملحوظ بالتباين في البيانات، وينتج إحصائية t وقيمة p. إذا كانت p ≤ 0.05 (وهو الحد المتعارف عليه)، فإننا نرفض الفرضية الصفرية التي تفترض تساوي المتوسطات. وهناك ثلاثة أنواع شائعة: اختبار لعينة واحدة، واختبار لعينتين مستقلتين، واختبار t للعينتين المترابطتين، ويُستخدم كل منها مع تصميم تجريبي مختلف.

اختبار T لعينة واحدة

يختبر اختبار t لعينة واحدة ما إذا كان متوسط عينة يختلف اختلافًا مهمًا إحصائيًا عن متوسط مجتمع معلوم أو مفترض. مثال على ذلك: «هل يختلف متوسط وقت التسليم لدينا اختلافًا مهمًا إحصائيًا عن معيار المجال البالغ 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 لعينتين مستقلتين

يقارن اختبار t لعينتين مستقلتين متوسطَي مجموعتين مستقلتين. على سبيل المثال: «هل يحقق البديل في اختبار A/B متوسط إيرادات أعلى من مجموعة التحكم؟» استخدم scipy.stats.ttest_ind(group_a, group_b). وتُعد المعلمة equal_var مهمة: اضبطها على equal_var=False (اختبار Welch's t) عندما يُحتمل أن يكون للمجموعتين تباينان مختلفان، وهو الإعداد الآمن الافتراضي لمعظم البيانات الواقعية.

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 افتراضيًا ثنائية الطرف: فهي تختبر ما إذا كان المتوسطان يختلفان في أي من الاتجاهين (أكبر أو أصغر). إذا كانت لديك فرضية اتجاهية («البديل يزيد الإيرادات»)، فاستخدم اختبارًا أحادي الطرف مع المعلمة 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 أن الفرق المرصود يعلو بمقدار خطأين معياريين عن القيمة المتوقعة وفق الفرضية الصفرية. في اختبار ثنائي الطرف عند α=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)

حجم التأثير: Cohen's d

تعتمد الدلالة الإحصائية على حجم العينة — فعند استخدام عينات كبيرة بما يكفي، تصبح حتى الفروق الضئيلة دالة إحصائيًا. يقيس Cohen's 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) التوزيع الطبيعي — البيانات في كل مجموعة تتبع توزيعًا طبيعيًا تقريبًا (ويكون الاختبار متينًا عندما n > 30 بفضل مبرهنة الحد المركزي)؛ (3) بالنسبة إلى اختبار Student's t ‏(equal_var=True)، تساوي التباينات. يخفف اختبار Welch's t ‏(equal_var=False) الافتراض الثالث، وهو الاختبار المفضل. عند حدوث انتهاك شديد للطبيعية مع عينات صغيرة (< 30)، استخدم اختبار Mann-Whitney U بدلًا منه.

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 Series مباشرةً إلى دوال scipy.stats — فهي تعمل بسلاسة مع Series وكذلك مع مصفوفات NumPy. ومن سير العمل الشائع: تصفية DataFrame للحصول على Series الخاصة بكل مجموعة، ثم تشغيل اختبار 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 عديدة في الوقت نفسه إلى زيادة احتمال الحصول على نتيجة إيجابية زائفة. فإذا أجريت 20 اختبارًا عند α=0.05، فإنك تتوقع نتيجة إيجابية زائفة واحدة بالصدفة. وتُعرف هذه باسم مشكلة المقارنات المتعددة. طبّق تصحيح 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's مع equal_var=False) يقارن مجموعتين مستقلتين، بينما يتعامل ttest_rel مع القياسات المترابطة. أبلغ دائمًا عن Cohen's d إلى جانب قيمة p للتمييز بين الدلالة الإحصائية والدلالة العملية. بعد ذلك سنختبر العلاقات بين المتغيرات الفئوية باستخدام اختبار كاي-تربيع.

البدء مجانًا

تعلم Python مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
30
الدروس
120

الأسئلة الشائعة

هل درس «اختبارات t لمقارنة المتوسطات» مجاني؟

نعم — نص درس «اختبارات t لمقارنة المتوسطات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Pandas & NumPy Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Pandas & NumPy Academy 4 دروس في المجموع.

ماذا ستتعلم في «اختبارات t لمقارنة المتوسطات»؟

أجرِ اختبارات t لعينة واحدة، ولعينتين مستقلتين، ولعينتين مترابطتين باستخدام scipy.stats، وفسّر فواصل الثقة تتمرن على Pandas & NumPy Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Pandas & NumPy Academy؟

لا تُشترط خبرة سابقة. Pandas & NumPy Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «اختبارات t لمقارنة المتوسطات»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Pandas & NumPy Academy هذا؟

نعم. كل درس في Pandas & NumPy Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الإحصاءات الوصفية واختبار التوزيع الطبيعي
  2. اختبارات t لمقارنة المتوسطات
  3. اختبار كاي-تربيع للاستقلالية
  4. تحليل التباين واختبارات ما بعد التحليل
← العودة إلى Pandas & NumPy Academy