اذهب إلى المحتوى

تحليل البيانات الاستكشافية لإثبات النظريات الإحصائية


زينة معلا

تقول الفرضية الأساسية لهذه السلسلة أنّ دمج البيانات مع الطرق العملية يمكنه الإجابة عن الأسئلة المطروحة وتوجيه القرارات في حالات الشك uncertainty.

يطرح آلان بي داوني Allen B. Downey مثالًا استلهمه من سؤال سمعه عندما كانت زوجته حاملًا بطفلهما الأول، وهو: هل تتأخر ولادة الأطفال الأوائل؟ إذا توجهنا بسؤالنا هذا إلى غوغل، فسنجد الكثير من النّقاشات حوله؛ إذ يَعتقد البعض أنها حقيقة، ويَعتقد آخرون أنها خرافة، كما يقول البعض الآخر عكس الحالة أي يولد الأطفال الأوائل باكرًا.

يلجأ المشاركون غالبًا في هذه النقاشات إلى تقديم بيانات تدعم اعتقادهم مثل:

اقتباس

أنجبت اثنتان من صديقاتي طفلهما الأول منذ فترة قريبة، ومَرّ أسبوعان بعد الموعد المتوقَّع قبل حدوث المخاض أو التحريض.

أنجبتُ طفلي الأول بعد أسبوعين من الموعد المتوقَّع، وأعتقد الآن أنّ طفلي الثاني سيأتي قبل الموعد بأسبوعين.

لا أعتقد أنّ هذا صحيح لأن أختي أتت باكرًا وهي الطفلة الأولى في العائلة، وكذلك الأمر بالنسبة للكثير من أطفال أقربائنا.

تُدعى التقارير هذه بالأدلة القولية anecdotal evidence، لأنها تستند إلى بيانات غير منشورة وغالبًا ما تكون تجارب شخصية، ولا حرج في استخدامها في الأحاديث العادية أي لا ننتقد أصحاب الأقوال السابقة، لكن قد نحتاج إلى أدلة أكثر إقناعًا وإلى إجابة أكثر وثوقية، وعندها لا يمكننا استخدام الأدلة غير الموثَّقة للأسباب التالية:

  • وجود عدد صغير من الحالات: إذا كان الحمل بالأطفال الأوائل أطول من بقية الأطفال، فسيكون الفارق صغيرًا غالبًا إذا ما وازنّاه بالاختلافات الطبيعية، وفي هذه الحالة علينا دراسة عدد كبير من حالات الحمل حتى نتأكد من وجود الفارق.
  • الانحياز الاختياري Selection bias: قد يكون المشاركون في النقاشات التي تدور حول هذا السؤال مهتمين بالأمر بسبب تأخر ولادة أطفالهم الأوائل، وفي هذه الحالة ستجعل عملية اختيار البيانات النتائجَ متحيزة.
  • الانحياز التأكيدي Confirmation bias: من المرجَّح أن يطرح الأشخاص الذين يعتقدون بصحّة هذه المقولة أمثلةً تؤكِّد أفكارهم، ومن المرجَّح أن يطرح الأشخاص الذين يعتقدون أنّ هذه المقولة خاطئة أمثلةً معاكسة.
  • عدم الدقة: غالبًا ما تكون الأدلة القولية قصصًا شخصيةً، وغالبًا ما تكون خاطئةً ومحرَّفةً ومكرَّرةً بصورة غير دقيقة.

إذًا، كيف يمكننا الوصول إلى نتيجة أفضل؟

نهج إحصائي

سنستخدِم أدوات الإحصاء لتحديد قيود الأدلة القولية، حيث تتضمّن هذه الأدوات ما يلي:

  • جمع البيانات: سنستخدِم بيانات مأخوذة من مسح كبير على مستوى الدولة، حيث صُمّم خصّيصًا لتوليد استنتاجات صحيحة إحصائيًا حول سكان الولايات المتحِدة الأمريكية.
  • الإحصائيات الوصفية: سنولِّد إحصائيات مهمتها تلخيص البيانات بإيجاز، وتقييم الطرق المختلفة التي يمكن فيها عرض البيانات.
  • تحليل البيانات الاستكشافية: سنبحث عن الأنماط المتكرّرة والفروق وميزات أخرى تعالج المسألة التي نناقشها، كما سنتحقق في الوقت ذاته من التناقضات ونحدِّد القيود.
  • التخمين Estimation: سنستخدم بيانات مأخوذة من عيّنة لتخمين صفات عامة الشعب.
  • اختبار الفرضيات: سنقيِّم التأثيرات الواضحة -مثل فرق بين مجموعتين من الأشخاص- فيما إذا كان قد حدث التأثير بمحض الصدْفة أم لا.

يمكننا الوصول إلى استنتاجات أكثر تبريرًا واحتمالًا لأن تكون صحيحةً عن طريق اتباع هذه الخطوات بعناية لتجنب العثرات والمطبّات.

المسح الوطني لنمو الأسرة

بدأت المراكز الأمريكية منذ عام 1973 بإجراء المسح الوطني لنمو الأسرة NSFG للسيطرة على الأمراض والوقاية منها CDC، إذ يهدف هذا المسح إلى جمع معلومات عن الحياة الأسريّة والزواج والطلاق والحمل والعقم واستخدام وسائل منع الحمل وصحّة النساء والرجال.

تُستخدَم نتائج المسح من أجل تخطيط الخدمات الصحية وبرامج التثقيف الصحي، ومن أجل إجراء دراسات إحصائية حول الأُسر والخصوبة والصحة، كما يمكنك الاطّلاع على صفحة المسح على الموقع الرسمي للمراكز

سنستخدم البيانات التي جمِّعت أثناء هذا المسح للتحقق من تأخر ولادة الأطفال الأوائل وللإجابة على أسئلة أخرى أيضًا، كما علينا فهم تصميم الدراسة من أجل استخدام هذه البيانات بفعالية.

يُعَدّ المسح الوطني لنمو الأسرة دراسةً مقطعيةً cross-sectional study، أي يخزِّن لقطةً سريعةً عن مجموعة محدَّدة في فترة محدَّدة من الزمن، كما تُعَدّ الدراسة الطولية longtitudal study البديل الأكثر شيوعًا، حيث تراقب مجموعةً معيَّنةً بصورة متكررة على مدار فترة زمنية.

أُجري المسح الوطني لنمو الأسرة سبع مرات، حيث تسمى كل عملية نشر بدورة cycle، كما سنستخدِم بيانات الدورة السادسة التي أجريت من شهر 1 من عام 2002 حتى شهر 3 من عام 2003.

يتلخص هدف المسح في الوصول إلى استنتاجات حول السكان، إذ تتراوح أعمار السكان المستهدَفِين من المسح الوطني لنمو الأسرة بين 15 و44 عامًا وهم أشخاص من الولايات المتحدة الأمريكية.

يجمع المسح المثالي بيانات من كل فرد، ولكن نادرًا ما يكون هذا متاحًا أو ممكنًا، وبدلًا من ذلك تُجمَع البيانات من مجموعة معيَّنة من السكان تدعى عيّنة sample، كما يُطلق على المشاركين في المسح اسم المستجيبون respondents.

يكون الهدف من إجراء الدراسات مقطعيًا هو جعلها تمثيلية representative عمومًا، بمعنى أن يكون لكل فرد من أفراد السكان فرصةً متساويةً من المشاركة، وعلى الرغم من كون هذه الحالة المثالية صعبة التحقيق عمليًا، إلا أنّ الأشخاص الذين يجرون الاستطلاعات يحاولون الاقتراب منها قدر الإمكان، كما لا يُعَدّ NSFG مسحًا تمثيليًا، وبدلًا من ذلك يُفرَط في أخذ العينات oversampled عمدًا.

يتعامل مصممو الدراسة مع ثلاث مجموعات وهي: الهسبانيون (حسب مكتب التعداد فإنّ الهسباني أو اللاتيني هو شخص من كوبا أو المكسيك أو بورتوريكو أو أمريكا الجنوبية أو الوسطى أو غيرها من الأصول الإسبانية بغض النظر عن العرق) والأفارقة الأمريكيون (هم مجموعة عرقية من أصول أفريقية تعيش في القارتين الأمريكيتين) والمراهقون بمعدَّلات أعلى من تمثيلهم الحقيقي في الولايات المتحدة الأمريكية، وذلك للتأكد من أنّ عدد المستجيبين في هذه المجموعات كبير بما يكفي لاستخلاص استدلالات إحصائية صحيحة.

يتمثّل الجانب السلبي من الإفراط في أخذ العينات بطبيعة الحال في صعوبة استخلاص استنتاجات حول عامة السكان بناءً على إحصاءات من المسح، وسنعود إلى هذه النقطة في وقت لاحق.

من المهم أن نكون على دراية بما يعرف بدليل الأسس والمعايير codebook عند التعامل مع هذا النوع من البيانات، إذ توثِّق هذه السلسلة تصميم الدراسة وأسئلة المسح وترميز إجابات المستجيبين، كما يتوفر دليل الأسس والمعايير ومرشِد المستخدِم لبيانات NSFG هنا.

استيراد البيانات

تتوفر الشيفرة والبيانات المستخدَمة في هذه السلسلة github، حيثسيكون لديك ملف باسم ThinkStats2/code/nsfg.py فور تنزيل الشيفرة، وإذا شغّلت هذا الملف فسيقرأ ملف البيانات ويشغّل بعض الاختبارات ويطبع رسالة "All tests passed" تشير إلى نجاح جميع الاختبارات، وسنرى فيما يلي مهمة هذا الملف.

توجد بيانات الحمل الخاصة بالدورة السادسة من NSFG في ملف يدعى 2002FemPreg.dat.gz، وهو ملف بيانات مضغوط بتنسيق نصي بسيط ASCII وأعمدة ذات عرض ثابت، كما يحتوي كل سطر من الملف على سجل record يحوي بيانات حمل واحد.

تنسيق الملف موثَّق في ملف قاموس لبرنامج ستاتا Stata وهو 2002FemPreg.dct، كما يُعَدّ ستاتا نظامًا برمجيًا إحصائيًا؛ أما "dictionary" أي القاموس في هذا السياق، فهو قائمة بأسماء وأنواع وفهارس المتغيرات التي تحدِّد في أيّ سطر يوجد كل متغير من المتغيرات.

فيما يلي بعض الأسطر من ملف 2002FemPreg.dctعلى سبيل المثال:

infile dictionary {
  _column(1)  str12  caseid    %12s  "RESPONDENT ID NUMBER"
  _column(13) byte   pregordr   %2f  "PREGNANCY ORDER (NUMBER)"
}

يصف هذا القاموس متغيرين: المتغير الأول caseid وهو سلسلة مكونة من 12 محرفًا تمثل معرِّف المستجيب؛ أما المتغير الثانيpregordr وهو عدد صحيح مؤلَّف من بايت واحد one-byte integer بحيث يشير إلى الحمل الذي يصفه هذا السجل لهذا المستجيب.

تحتوي الشيفرة التي حمَّلتها على thinkstats2.py، وهو وحدة بايثون تحتوي على العديد من الأصناف والدوال المستخدَمة في هذه السلسلة بما في ذلك الدوال القارئة لقاموس ستاتا وملف بيانات NSFG، وإليك كيفية استخدامها فيnsfg.py:

def ReadFemPreg(dct_file='2002FemPreg.dct',
                dat_file='2002FemPreg.dat.gz'):
    dct = thinkstats2.ReadStataDct(dct_file)
    df = dct.ReadFixedWidth(dat_file, compression='gzip')
    CleanFemPreg(df)
    return df

يأخذ ReadStataDct اسم ملف القاموس ويُعيد dct، الذي هو كائن من النوع FixedWidthVariables يحتوي على معلومات من ملف القاموس، كما يوفر dct التابع ReadFixedWidth الذي يقرأ ملف البيانات.

إطارات البيانات

النتيجة التي يُعيدها التابع ReadFixedWidth هي إطار بيانات DataFrame، وهو بنية البيانات الأساسيّة التي توفرها بانداز pandas التي هي حزمة بيانات وإحصائيات خاصة بلغة بايثون، كما ستُستَخدم في هذه السلسلة.

يتألف إطار البيانات من سطر لكل سجل، وفي هذه الحالة يكون سطر لكل حمل وعمود لكل متغير، كما يتألف إطار البيانات من أسماء المتغيرات وأنواعها، ويوفر توابع مهمتها الوصول إلى البيانات وتعديلها.

إذا طبعنا df فسنحصل على عرض مقطوع truncated view للأسطر والأعمدة، وعلى شكل إطار البيانات الذي يتألف من 13593 سطر/سجل، و244 عمود/متغير.

>>> import nsfg
>>> df = nsfg.ReadFemPreg()
>>> df
...
[13593 rows x 244 columns]

عُرض جزء من الخرج وأخُفي الباقي لأنّ حجم إطار البيانات أكبر من أن يُعرض كاملًا، ويُظهر السطر الأخير عدد الأسطر والأعمدة، كما تُعيد سمة الأعمدة columns سلسلةً من أسماء الأعمدة بتنسيق سلاسل الترميز الموحَّد Unicode:

>>> df.columns
Index([u'caseid', u'pregordr', u'howpreg_n', u'howpreg_p', ... ])

تكون نتيجة ما سبق Index أي فهرسًا، وهو بنية بيانات من حزمة البانداز pandas، كما سنشرح بنية الفهرس لاحقًا، لكننا سنتعامل معه حاليًا على أساس قائمة list:

>>> df.columns[1]
'pregordr'

للوصول إلى أحد أعمدة إطار البيانات، يمكننا استخدام اسم العمود على أساس مفتاح:

>>> pregordr = df['pregordr']
>>> type(pregordr)
<class 'pandas.core.series.Series'>

تكون نتيجة ما سبق هي Series أي سلسلةً، وهي بنية بيانات في حزمة البانداز pandas أيضًا.

تشبه السلسلة نوع القائمة list الموجودة في لغة البايثون مع بعض الميزات الإضافية، وسنحصل على الفهارس والقيم المقابلة لها عند طباعة السلسلة كما يلي:

>>> pregordr
0     1
1     2
2     1
3     2
...
13590    3
13591    4
13592    5
Name: pregordr, Length: 13593, dtype: int64

نلاحظ في هذا المثال أنّ الفهارس هي أعداد صحيحة موجودة بين العددين 0 و13592، ولكن يمكنها أن تكون أيًا من الأنواع القابلة للفرز عمومًا، كما تُعَدّ العناصر أعدادًا صحيحةً ويمكنها أن تكون أيّ نوع آخر أيضًا.

يتضمن السطر الأخير اسم المتغير وطول السلسلة ونوع البيانات، حيث يُعَدّ int64 أحد الأنواع التي توفرها مكتبة نمباي NumPy، وإذا جرّبنا هذا المثال على آلة تعمل بنظام 32-بِتّ، فقد نحصل علىint32.

يمكن الوصول إلى عناصر السلسلة باستخدام فهارس وشرائح من الأعداد الصحيحة:

>>> pregordr[0]
1
>>> pregordr[2:5]
2    1
3    2
4    3
Name: pregordr, dtype: int64

تكون نتيجة عامِل الفهرس هي int64، ونتيجة الشريحة سلسلةً أخرى، كما يمكننا الوصول إلى أعمدة إطار البيانات عن طريق استخدام صيغة الاستدعاء النقطية، أي كما يلي:

>>> pregordr = df.pregordr

لا يمكن استخدام هذه الصيغة إلا إذا كان اسم العمود مُعرِّفًا صالحًا في بايثون، لذا يجب أن يبدأ بحرف ولا يمكن أن يحتوي على فراغات، …إلخ.

المتغيرات

وجدنا في مجموعة بيانات NSFG متغيرَين اثنين وهما caseid وpregordr، كما لاحظنا وجود 244 متغير في كامل مجموعة بيانات NSFG.

سنستخدِم المتغيرات التالية للوصول إلى الاستنتاجات في هذه السلسلة:

  • caseid عدد صحيح يمثل معرِّف المستجيب.
  • prglngth عدد صحيح يمثل مدة الحمل مقاسة بالأسابيع.
  • outcome: رمز صحيح يمثِّل نتيجة الحمل، حيث يشير الرقم 1 إلى تمام الولادة والطفل حي.
  • pregordr: عدد تسلسلي للحمل، إذ يكون رمز الحمل الأوّل للمستجيب هو 1، ورمز الحمل الثاني هو 2 وهكذا على سبيل المثال.
  • birthord: عدد تسلسلي للولادات الحية، حيث يكون رمز الطفل الأول للمستجيب هو 1؛ أما بالنسبة للولادات غير الحية فيبقى الحقل فارغًَا.
  • birthwgt_lb وbirthwgt_oz: يمثِّلان وزن الطفل عند ولادته، مقدرًا بالرطل وبالأوقية.
  • agepreg: عمر الأم في نهاية الحمل.
  • finalwgt: الوزن الإحصائي المرتبط بالمستجيب، وهو قيمة عشرية تمثِّل عدد سكان الولايات المتحِدة الأمريكية الذين يمثلهم المستجيب.

إذا قرأت دليل الأسس والمعايير بعناية، فسترى أنّ العديد من المتغيرات هي متغيرات محسوبة القيمة recodes، أي أنها ليست جزءًا من البيانات الأولية raw data التي جُمِعت أثناء المسح، بل حُسِبت باستخدام البيانات الأولية، فمثلًا، يساوي المتغير prglngth للولادات الحية المتغير الأوليwksgest -أي عدد أسابيع الحمل- إذا كان متوفرًا، وإلا فسيُقدَّر باستخدام mosgest * 4.33 -أي عدد أشهر الحمل مضروب بمتوسط عدد الأسابيع في الشهر الواحد-.

تستند عمليات إعادة الترميز غالبًا إلى المنطق الذي يتحقق من اتساق البيانات ودقتها، كما من الجيد عمومًا اللجوء إلى استخدام إعادة الترميز إذا كانت متاحةً وما لم يكن هناك سبب مقنع يجبرنا على معالجة البيانات الأولية بأنفسنا.

عمليات التحويل

يتعين علينا غالبًا عند استيراد هذا النوع من البيانات التحقق من الأخطاء والتعامل مع قيم خاصة وتحويل البيانات إلى صيغ مختلفة وإجراء العمليات الحسابية، حيث تُسمى هذه العمليات بتنقية تنظيف البيانات data cleaning.

يحتويnsfg.py على CleanFemPreg، وهو دالة تُنقي المتغيرات التي نُخطِّط لاستخدامها.

def CleanFemPreg(df):
    df.agepreg /= 100.0

    na_vals = [97, 98, 99]
    df.birthwgt_lb.replace(na_vals, np.nan, inplace=True)
    df.birthwgt_oz.replace(na_vals, np.nan, inplace=True)

    df['totalwgt_lb'] = df.birthwgt_lb + df.birthwgt_oz / 16.0  

يحتوي متغير agepreg على عمر الأم في نهاية الحمل، كما يُرمَّز agepreg في ملف البيانات ليكون رقمًا صحيحًا يعبر عن السنوات، وبالتالي يقسِّم السطر الأول كل عنصر من عناصر agepreg على 100، مما ينتج عنه قيمة عشرية تمثِّل السنوات، كما يحتوي المتغيران birthwgt_lb وbirthwgt_oz على وزن الطفل بالرطل والأوقية على الترتيب، وذلك لحالات الحمل التي تنتهي بولادة حيّة، كما يَستخدِمان عدة رموز خاصة:

97      NOT ASCERTAINED
98      REFUSED
99      DON'T KNOW

تكمن خطورة القيم الخاصة المرمَّزة على أساس أعداد في عدم معالجتها بصورة صحيحة، إذ يمكنها توليد نتائج وهمية، مثل طفل بوزن 99 رطل.

يستبدل التابع replace هذه القيم لتكون np.nan، وهي قيمة عشرية خاصة تمثِّل "ليس عددًا" أي Not a Number، كما تطلب راية inplace من التابع replace تعديل السلسلة الموجودة عوضًا عن إنشاء سلسلة جديدة.

تُعيد جميع العمليات الرياضية nan إذا كان أيًا من الوسطاء nan أي "ليس عددًا"، وذلك على أساس جزء من معيار معهد مهندسي الكهرباء والإلكترونيات IEEE للعدد العشري، كما يلي:

>>> import numpy as np
>>> np.nan / 100.0
nan

لذا غالبًا ما تفي الحسابات باستخدام nan بالغرض وتعطي النتيجة المطلوبة، كما تعالِج معظم دوال البانداز pandas ظهور nan بصورة مناسبة، لكن سنواجه مشكلةً متكرِّرةً وهي التعامل مع بيانات ناقصة.

يُنشِئ السطر الأخير من CleanFemPreg عمودًا جديدًا totalwgt_lb، ويدمج الوزن بالرطل والأوقية في كمية واحدة تقاس بالرطل.

اقتباس

ملاحظة هامة: عند إضافة عمود جديد إلى إطار بيانات، فيجب استخدام صيغة القاموس بالشكل التالي:

    # CORRECT
    df['totalwgt_lb'] = df.birthwgt_lb + df.birthwgt_oz / 16.0 

وليس الصيغة النقطية التالية:

    # WRONG!
    df.totalwgt_lb = df.birthwgt_lb + df.birthwgt_oz / 16.0 

يضيف الإصدار الذي يحتوي على الصيغة النقطية سمةً إلى كائن إطار البيانات، ولكن لايُتعامَل مع هذه السمة على أنها عمود جديد.

التحقق

قد تظهر أخطاء عند تصدير البيانات من بيئة برمجية معينة واستيرادها إلى بيئة أخرى، وعندما نتعرَّف على مجموعة بيانات جديدة، فقد تفسر البيانات بصورة غير صحيحة، أو قد تفهم أمرًا ما بصورة خاطئة، فإذا خصصت وقتًا للتحقق من صحة البيانات، فستستطيع توفير الوقت لاحقًا وستتجنب الوقوع في أخطاء.

تتمثَّل إحدى طرق التحقق من البيانات في حساب الإحصائيات الأساسية وموازنتها مع النتائج المنشورة، إذ يلخِّص بدليل الأسس والمعايير الخاص بالـ NSFG كل متغير مثلًا.

إليك جدولًا بالخرج، حيث رُمِّز كل خرج حمل:

value   label                  Total
1       LIVE BIRTH              9148
2       INDUCED ABORTION        1862
3       STILLBIRTH               120
4       MISCARRIAGE             1921
5       ECTOPIC PREGNANCY        190
6       CURRENT PREGNANCY        352

يوفر صنف السلسلة Series تابعًا باسم value_counts مهمته حساب عدد المرات التي تظهر فيها كل قيمة، فإذا حددنا سلسلة outcome من إطار البيانات،فيمكننا استخدام value_counts لموازنتها مع البيانات المنشورة كما يلي:

>>> df.outcome.value_counts().sort_index()
1    9148
2    1862
3     120
4    1921
5     190
6     352

تكون نتيجة value_counts سلسلةً؛ أما ()sort_index فسيفرز السلسلة حسب الفهرس بحيث تظهر القيم بالترتيب. وسنجد أن القيم في outcome صحيحة عند موازنة النتائج بالجدول المنشور، وبالمثل يكون هذا هو الجدول المنشور لـ birthwgt_lb:

value   label                  Total
.       INAPPLICABLE            4449
0-5     UNDER 6 POUNDS          1125
6       6 POUNDS                2223
7       7 POUNDS                3049
8       8 POUNDS                1889
9-95    9 POUNDS OR MORE         799

وهذه هي عدد مرات ظهور القيم:

>>> df.birthwgt_lb.value_counts(sort=False)
0        8
1       40
2       53
3       98
4      229
5      697
6     2223
7     3049
8     1889
9      623
10     132
11      26
12      10
13       3
14       3
15       1
51       1

تُعَدّ الإحصاءات counts الخاصة بـ 6 و7 و8 أرطالًا صحيحةً، وإذا جمعنا الإحصاءات للأرقام بين 0-5، و9-95 فسنجد أنها صحيحة أيضًا. ولكن إذا نظرنا عن كثب، فسنلاحظ وجود خطأ في قيمة واحدة وهي الطفل بوزن 51 رطلًا، لذا سنضيف سطرًا إلى CleanFemPreg للتعامل مع هذا الخطأ:

df.loc[df.birthwgt_lb > 20, 'birthwgt_lb'] = np.nan

تستبدِل هذه التعليمة القيم غير الصالحة لتكون np.nan، حيث تُوفِّر السمة loc عدة طرق لتحديد الصفوف والأعمدة من إطار البيانات، إذ يكون أول تعبير محاط بقوسين في هذا المثال مُفهرس الصف؛ أما التعبير الثاني فسيحدد العمود.

ينتج عن التعبير df.birthwgt_lb > 20 سلسلةً من النوع البولياني bool، حيث تشير القيمة الصحيحة True إلى صحة الشرط، كما ستحدِّد السلسلة البوليانية المستخدَمة على أساس فهرس العناصر التي تحقق الشرط فقط.

التفسير

يجب التفكير بمستويَين في آن معًا لنستطيع العمل مع البيانات بفعالية، وهما مستوى الإحصائيات ومستوى السياق.

سنلقي نظرةً على تسلسل sequence نتائج بعض المستجيبين مثلًا، كما يتعين علينا إجراء بعض المعالجة من أجل جمع بيانات الحمل لكل مستجيب، وذلك لأن ملفات البيانات منظَّمة، وهذا مثال على دالة تفعل ذلك:

def MakePregMap(df):
    d = defaultdict(list)
    for index, caseid in df.caseid.iteritems():
        d[caseid].append(index)
    return d

يُعَدّ df إطار بيانات يحتوي على بيانات الحمل، كما يحصي تابع iteritems الفهرس - أي عدد الصنف- ومعرِّف الحالة caseid لكل حمل؛ أما d فهو قاموس يعيّن لكل معرِّف حالة قائمةً من الفهارس، وفي حال عدم معرفتك السابقة بـ defaultdict فهو وحدة collections في بايثون. كما يمكننا البحث عن مستجيب والحصول على فهارس حمل خاصة به باستخدام d.

يبحث المثال التالي عن مستجيب ويطبع قائمةً بنتائج الحمل الخاص به:

>>> caseid = 10229
>>> preg_map = nsfg.MakePregMap(df)
>>> indices = preg_map[caseid]
>>> df.outcome[indices].values
[4 4 4 4 4 4 1]

تُعَدّ indices قائمةً بفهارس حالات الحمل الموافقة للمستجيب صاحب المعرِّف 10229.

يؤدي استخدام هذه القائمة على أساس فهرس لـ df.outcome إلى تحديد الأصناف المشار إليها وإنتاج سلسلة، ولكننا حددنا سمة values بدلًا من طباعة السلسلة كاملة، والتي هي مصفوفة نمباي NumPy array، حيث يدل رمز الخرج 1 على أنّ الولادة حية، ويدل الرمز 4 على حدوث إجهاض -أي انتهى الحمل انتهاءً ذاتيًا وغالبًا بدون سبب طبي معروف-.

يُعَدّ احتمال مصادفة مستجيب حصل معه هذا ممكنًا إحصائيًا، فالإجهاض أمر شائع، إذ أبلغ مستجيبون آخرون عن عدة حالات إجهاض أو أكثر، ولكن إذا نظرنا إلى مستوى السياق، فسنجد هذه البيانات تحكي قصة امرأة حملت ست مرات وانتهى كل حمل بإجهاض؛ أما الحالة السابعة والأخيرة فقد انتهت بولادة حية، وإذا فكرنا بهذه البيانات بتعاطف، فمن الطبيعي أن نتأثر بالقصة التي تحكيها.

يمثِّل كل سجل في مجموعة بيانات NSFG فردًا قدَّم إجابات صادقة عن العديد من الأسئلة الشخصية والصعبة، ويمكننا بالطبع استخدام هذه البيانات للإجابة عن أسئلة إحصائية حول الحياة الأسرية والإنجاب والصحة، كما علينا في الوقت ذاته النظر في الأشخاص الذين تمثلهم هذه البيانات ونقدِّم لهم الاحترام والامتنان.

تمارين

التمرين الأول

ستجد في المستودع repository الذي حمَّلته ملفًا باسم chap01ex.ipynb وهو IPython notebook أي مفكرة من نوع IPython، كما يمكنك تشغيل IPython notebook من سطر الأوامر command line بالصورة التالية:

$ ipython notebook &

يجب عليك إذا ثُبِّت IPython تشغيل خادم يعمل في الخلفية وفتح متصفح ويب من أجل عرض المفكرة، وإذا لم تكن معتادًا على IPython، فمن الأفضل البدء من IPython notebook، والذي يجب لفتحه تشغيل ما يلي:

$ ipython notebook &

يجب فتح نافذة متصفح ويب جديدة، وإن لم يحصل هذا، فستوفِّر رسالة بدء التشغيل محدِّد موارد مُوحَّد هو رابط URL، والذي يمكنك تحميله في المتصفح، وغالبًا ما يكون http://localhost:8888، كما يجب أن تُظهِر النافذة الجديدة قائمةً بكل الـ notebooks الموجودة في المستودع.

افتح chap01ex.ipynb، حيث مُلِئت بعض الخلايا وعليك تنفيذها؛ أما الخلايا الأخرى فستزودك بتعليمات حول التمارين التي يجب عليك تجريبها.

اقتباس

ملاحظة: حل هذا التمرين موجود في chap01soln.ipynb.

التمرين الثاني

ستجد في المستودع repository الذي حمَّلته ملفًا باسم chap01ex.py، اكتب دالةً تقرأ ملف المستجيب 2002FemResp.dat.gz باستخدام هذا الملف على أساس نقطة انطلاق. يكون المتغير pregnum هو ترميز يشير إلى عدد المرات التي حدث فيها حمل مع المستجيب، وبالتالي اطبع عدد القيم value counts الخاصة بهذا المتغير ووازنها مع النتائج المنشورة في دليل الأسس والمعايير لـ NSFG.

يمكنك التحقق من ملفات المستجيب والحمل عن طريق موازنة متغير pregnum مع عدد السجلات في ملف الحمل أيضًا، كما يمكنك استخدام nsfg.MalePregMap لإنشاء قاموس يصل بين كل caseid إلى قائمة من الفهارس في إطار بيانات الحمل.

اقتباس

ملاحظة: حل هذا التمرين موجود في chap01soln.py.

التمرين الثالث

يُعَدّ العمل على مشروع يهمّك هو الطريقة الأفضل لتعلُّم الإحصاء، فهل ترغب بالتحقيق في سؤال مثل "هل تتأخر ولادة الأطفال الأوائل؟" فكِّر في أسئلة تجدها مثيرةً للاهتمام أو أفكار حول الحكمة التقليدية، أو مواضيع مثيرة للجدل، وانظر فيما إذا كنت تستطيع صياغة سؤال يفسح لك المجال أمام استقصاء إحصائي، وبعدها ابحث عن البيانات لكي تساعدك على تناول السؤال، وتُعَدّ الحكومات مصادر جيدة لأن البيانات من البحوث العامة غالبًا ما تكون متاحة مجانًا دون مقابل.

إليك بعض المواقع الجيدة التي يمكنك البدء منها data.gov وفي المملكة المتحدة الموقع التالي gov.uk.

توجد اثنتان من مجموعات البيانات المفضلة لدينا، وهما المسح الاجتماعي العام والمسح الاجتماعي الأوروبي.

إذا أجاب أحد ما عن سؤالك، فألق نظرةً عن كثب لترى ما إذا كان الجواب مبررًا، فقد تكون هناك أخطاء في البيانات أو التحليل تجعل النتيجة غير موثوقة، ويمكنك في هذه الحالة إجراء تحليل آخر على البيانات ذاتها أو البحث عن مصدر أفضل للبيانات.

إذا وجدت ورقة بحث منشورة تتناول سؤالك، فيجب أن تكون قادرًا على الحصول على البيانات الأولية، حيث يتيح الكثير من المؤلفِين بياناتهم على الإنترنت، ولكن قد تضطر إلى التواصل مع المؤلفِين من أجل البيانات الحساسة، وتخبرهم بما تخطط له لاستخدام البيانات، أو ربما عليك الموافقة على شروط محدَّدة، لذلك كن مثابرًا.

المفاهيم الأساسية

  • الأدلة القولية anecdotal evidence: أدلة جُمِّعت بصورة عرضية بدلًا من دراسة مصمَّمة بصورة جيدة، وغالبًا ما تكون شخصية.
  • السكان population: مجموعة من أشخاص هم محط اهتمام دراستنا، وغالبًا ما تشير كلمة "سكّان" إلى مجموعة من الأشخاص؛ إلا أنه يمكن استخدام هذا المصطلح لمواضيع أخرى أيضًا.
  • الدراسة المقطعية cross-sectional study: هي الدراسة التي تجمع البيانات عن السكان في نقطة محدَّدة من الزمن.
  • دورة cycle: في الدراسة المقطعية التي تتكرر عدة مرات، يُدعى كل تكرار للدراسة بدورة.
  • الدراسة الطولية longitudinal study: هي الدراسة التي تتبع السكان على طول فترة من الزمن، وتجمع البيانات من المجموعة ذاتها بصورة متكرِّرة.
  • سجل record: في مجموعة البيانات، فإنّ السجل هو تجميعة من المعلومات حول شخص واحد أو موضوع معين.
  • مستجيب respondent: هو الشخص الذي يستجيب للمسح الإحصائي.
  • عيّنة sample: هي مجموعة فرعية من السكان الذين تُجمع البيانات منهم.
  • تمثيلي representative: تكون العينة تمثيليةً إذا كان لكل فرد من السكّان فرصةً متساويةً ليكون في العينة.
  • الإفراط في أخذ العينات oversampling: تعتمد هذه التقنية على زيادة تمثيل مجموعة فرعية من السكّان لتجنب الأخطاء الناجمة عن صغر أحجام العينات.
  • البيانات الأولية raw data: هي القيم التي تُجمَع وتُسجَّل مع القليل من عمليات التحقّق أو الحساب أو التفسير إن وجدت.
  • متغير محسوب القيمة recode: قيمة مولَّدة عن طريق حسابات على البيانات الأولية أو عن طريق تطبيق منطق آخر عليها.
  • تنقية البيانات data cleaning: هي العمليات التي تشمل التحقق من البيانات وتحديد الأخطاء والتحويل بين أنواع البيانات والتمثيلات، …إلخ.

ترجمة -بتصرف- للفصل الأول Chapter 1 Exploratory data analysis من كتاب Think Stats: Exploratory Data Analysis in Python.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...