الأسبوع 9: التصورات المتقدمة والسردية
🎯 أهداف التعلم
بنهاية هذا الأسبوع ستكون قادرًا على:
- بناء تصورات مقسّمة/متعددة اللوحات تُظهر علاقة مفصّلة حسب متغير فئوي ثالث.
- استخدام اللون والترتيب والتوضيح بشكل مقصود لجعل فكرة المخطط واضحة بنظرة واحدة.
- اختيار لوحة ألوان هادفة وصديقة لعمى الألوان بدلاً من الافتراضية الأولى.
- نقد مخطط لما يُظهره وما لا يُظهره بأمانة.
- حفظ مخطط منتهٍ في ملف لتضمينه في تقرير.
الدرس
التقسيم إلى لوحات: إضافة بُعد ثالث بألواح
يُظهر مخطط الانتشار متغيرين رقميين؛ تضيف أدوات التقسيم في seaborn بُعدًا ثالثًا — فئويًا عادةً — عبر التقسيم إلى شبكة من الألواح الصغيرة القابلة للمقارنة بدلاً من حشر كل شيء في مخطط واحد:
import seaborn as sns
import matplotlib.pyplot as plt
sns.relplot(
data=df,
x="reading_score",
y="writing_score",
col="test_preparation_course", # لوح واحد لكل فئة، جنبًا إلى جنب
hue="gender", # لون داخل كل لوح
)
plt.show()
يجيب هذا عن سؤال متعدد المتغيرات حقًا في شكل واحد: هل تبدو علاقة القراءة/الكتابة مختلفة للطلاب الذين أكملوا التحضير للاختبار مقابل من لم يكملوه، و هل يختلف ذلك حسب الجنس — كل ذلك دفعة واحدة، وقابل للمقارنة جنبًا إلى جنب لأن كل لوح يشارك نفس مقاييس المحاور. إضافة row= جنبًا إلى جنب مع col= توسّع هذا إلى شبكة كاملة — بُعد عبر الأعمدة، وآخر عبر الصفوف:
sns.relplot(
data=df, x="reading_score", y="writing_score",
col="test_preparation_course", row="lunch", hue="gender",
)
أصبح هذا الآن شكلاً برباعية متغيرات فعلية (القراءة، الكتابة، التحضير للاختبار، الغداء، الجنس — خمسة في الواقع) — مثير للإعجاب، لكن يستحق موازنته مع خطر "أبعاد كثيرة جدًا في مخطط واحد" أدناه.
ترتيب الفئات بشكل مقصود
بشكل افتراضي، غالبًا ما تُرتَّب المحاور الفئوية أبجديًا أو حسب الظهور الأول — وهو نادرًا ما يكون الترتيب الأكثر قابلية للقراءة. الترتيب الصريح حسب قيمة ذات معنى (مثل متوسط المجموعة) يجعل نمط المخطط الشريطي مقروءًا فورًا بدلاً من مطالبة القارئ بالبحث عنه:
order = df.groupby("parental_level_of_education")["math_score"].mean().sort_values().index
sns.barplot(data=df, x="parental_level_of_education", y="math_score", order=order)
plt.xticks(rotation=45, ha="right")
plt.title("Average math score by parental education level (ordered)")
plt.tight_layout()
plt.show()
تحسب sns.barplot (على خلاف مخطط شريطي عادي في matplotlib) المتوسط تلقائيًا لكل فئة وتضيف أشرطة خطأ تمثل عدم اليقين — يستحق معرفته حتى لا تخلط بينه وبين الأعداد الخام.
اختيار لوحة مقصودة وصديقة لعمى الألوان
لوحة seaborn الافتراضية نقطة انطلاق معقولة، لكن اختيارات الألوان الهادفة تُوصِل أكثر: استخدم لوحة متسلسلة (من الفاتح إلى الغامق) لمتغير رقمي مرتب، لوحة متباينة (لونان يلتقيان عند نقطة وسطى محايدة) للقيم التي ترتفع وتنخفض بمعنى حقيقي حول نقطة مركزية (مثل "coolwarm" في الخريطة الحرارية للارتباط في الأسبوع 8)، ولوحة نوعية للفئات غير المرتبة. لوحة "colorblind" في seaborn خيار افتراضي آمن ومقصود كلما احتاج اللون إلى تمييز الفئات بموثوقية لكل قارئ:
sns.barplot(data=df, x="parental_level_of_education", y="math_score", order=order, palette="colorblind")
ما يقارب 1 من كل 12 رجلاً يعاني من شكل ما من أشكال ضعف رؤية الألوان — اعتماد لوحة آمنة لعمى الألوان كافتراضي لا يكلف شيئًا ولا يستبعد أحدًا، وهذا سبب كونها خيارًا افتراضيًا معقولاً لا حالة خاصة.
توضيح النقطة مباشرة
يكون المخطط ذو الادعاء المحدد ("الطلاب الذين أكملوا التحضير للاختبار حصلوا، في المتوسط، على N نقطة أعلى") أكثر إقناعًا عندما يكون ذلك الرقم مرئيًا على المخطط نفسه، لا متروكًا للقارئ ليحسبه من مواضع المحاور:
means = df.groupby("test_preparation_course")["math_score"].mean()
ax = means.plot(kind="bar")
for i, value in enumerate(means):
ax.text(i, value + 1, f"{value:.1f}", ha="center")
plt.ylabel("Average math score")
plt.title("Average math score by test preparation status")
plt.show()
حفظ مخطط لتقريرك
بمجرد الانتهاء من مخطط، تكتبه plt.savefig إلى ملف صورة — مفيد لتضمينه في تقرير مكتوب بدلاً من الاكتفاء بمشاهدته ضمن السياق فقط:
plt.savefig("math_score_by_prep.png", dpi=150, bbox_inches="tight")
يتحكم dpi=150 في دقة الصورة (أعلى = أوضح، لكن ملف أكبر)؛ يقصّ bbox_inches="tight" الفراغ الزائد حول الشكل. استدعِ plt.savefig(...) قبل plt.show() في نفس الخلية — بعض البيئات تمسح الشكل الحالي بمجرد عرضه.
مخططات أمينة: ما يجب الانتباه إليه
بعض الطرق الشائعة التي تُضلِّل بها المخططات، حتى دون أي أرقام مُلفَّقة:
- محور y مبتور: بدء المحور y لمخطط شريطي أعلى من 0 يبالغ بصريًا في الفروقات الصغيرة. يجب أن تبدأ المخططات الشريطية دائمًا تقريبًا من 0؛ مخططات الخط/الانتشار التي تقارن التغيّر استثناء أكثر قابلية للتبرير.
- نطاق محور مُنتقى بعناية: التقريب إلى نطاق x ضيق يمكن أن يجعل الضجيج يبدو كاتجاه ذي معنى.
- مقاييس ألوان غير موسومة أو مضللة: يجب توسيم مقياس ألوان الخريطة الحرارية، وحسب الأسبوع 8، تثبيته عند نطاق ثابت لقابلية مقارنة حقيقية.
- الاكتظاظ البصري: كثرة النقاط المتداخلة (تُعالَج بـ
alpha، حسب الأسبوع 8، أو التجميع) يمكن أن تخفي بصريًا الكثافة الفعلية لعلاقة ما.
يكتسب المخطط السردي الثقة بجعل أمانته سهل التحقق منه، لا بمجرد أن يبدو أنيقًا فقط.
⚠️ أخطاء شائعة
- تكديس أبعاد كثيرة جدًا في مخطط واحد. يمكن لـ
row=/col=/hue=معًا إظهار 4-5 متغيرات تقنيًا في آن واحد، لكن مخططًا يحتاج إلى فقرة من الشرح لفكّه قد تجاوز عادةً نقطة كونه أكثر إفادة فعليًا من مخططين أبسط. - اختيار لوحة للمظهر لا للمعنى. لوحة قوس قزح على متغير مرتب (مثل درجات الاختبار المقسمة إلى 5 نطاقات) تجعل الترتيب أصعب إدراكًا مما ستفعله لوحة متسلسلة مناسبة.
- نسيان أن
plt.savefig()يجب أن يسبقplt.show(). استدعاؤهما بالترتيب الخاطئ يمكن أن يحفظ صورة فارغة في بعض البيئات. - الخلط بين أشرطة خطأ
sns.barplotوشيء آخر. إنها تمثل عدم اليقين في المتوسط المقدَّر (بشكل افتراضي، فترة ثقة bootstrap) — لا التشتت الخام للبيانات، وهو ما يُظهره مخطط الصندوق (الأسبوع 7/8) بدلاً من ذلك.
🧩 التحديات
أنشئ مخطط انتشار مقسّم لـ math_score مقابل reading_score، بلوح واحد لكل فئة lunch.
ابنِ مخططًا شريطيًا لمتوسط writing_score حسب race_ethnicity، بأشرطة مرتبة صراحةً من الأدنى إلى الأعلى متوسطًا.
خذ أحد مخططاتك الشريطية من هذا الأسبوع واضبط عمدًا plt.ylim(bottom=some_value_above_0). قارن النسختين جنبًا إلى جنب — كيف تضلل النسخة المبتورة بصريًا بشأن حجم الفرق؟
خذ مخططًا شريطيًا لمتوسطات المجموعات ووضّح كل شريط بقيمته الرقمية فوقه مباشرة، كما هو موضح في الدرس.
خذ مخططًا من هذا الأسبوع يستخدم اللون لتمييز الفئات، وأعد إنشاءه بـ palette="colorblind". هل يبقى التمييز بين الفئات واضحًا؟
احفظ أحد مخططات هذا الأسبوع المنتهية في ملف PNG باستخدام plt.savefig، مع dpi=150 وbbox_inches="tight".
🤔 أسئلة سقراطية
- التقسيم حسب
test_preparation_courseوالتلوين حسبgenderيضع أربع تركيبات من المعلومات في شكل واحد. عند أي نقطة تبدأ إضافة المزيد من الأبعاد إلى مخطط واحد في جعله أصعب قراءةً بدلاً من أكثر إفادة؟ كيف تقرر متى تُقسِّم إلى أشكال منفصلة بدلاً من ذلك؟ - تُظهر
sns.barplotمتوسطات مع أشرطة خطأ، بينما يُظهر مخطط شريطي عادي للأعداد الخام شيئًا مختلفًا تمامًا. ماذا يمكن أن يحدث خطأً لو افترض القارئ أنsns.barplotيُظهر أعدادًا؟ - تعرف الآن عدة طرق يمكن أن يُضلِّل بها مخطط دون أي أرقام مُلفَّقة (محاور مبتورة، نطاقات مُنتقاة بعناية، مقاييس غير موسومة). بناءً على ذلك، ما معيارك في تحديد ما إذا كان مخطط صنعته لتقرير الأسبوع 10 الخاص بك "أمينًا"، أبعد من مجرد "الأرقام صحيحة"؟
- تناسب اللوحات المتسلسلة والمتباينة والنوعية كل منها نوعًا مختلفًا من المتغيرات. ماذا سيحدث بصريًا بشكل خاطئ لو استخدمت لوحة متباينة (لونان يلتقيان عند نقطة وسطى محايدة) على متغير فئوي عادي غير مرتب مثل
race_ethnicity؟ - لوحة صديقة لعمى الألوان لا تكلف شيئًا لاستخدامها كافتراضي. هل يمكنك التفكير في اختيارات أخرى "متاحة افتراضيًا بلا تكلفة" من أسابيع سابقة (تسميات المحاور، عناوين المخططات، تجنّب اللون كوسيلة وحيدة لتمييز المجموعات) تتبع نفس المبدأ؟