9 الطبقات (Layers)
9.1 مقدمة
في الفصل 1، تعلمت ما هو أكثر بكثير من مجرد كيفية إنشاء مخططات تشتت (scatterplots)، ومخططات أعمدة (bar charts)، ومخططات صندوقية (boxplots). لقد تعلمت الأساس الذي يمكنك استخدامه لإنشاء أي نوع من المخططات البيانية باستخدام حزمة ggplot2.
في هذا الفصل، ستتوسع في هذا الأساس حيث ستتعرف على القواعد الطبقية للرسومات (Layered grammar of graphics). سنبدأ بغوص أعمق في جماليات الربط (Aesthetic mappings)، والأشكال الهندسية (Geometric objects)، والأوجه (Facets). بعد ذلك، ستتعلم عن التحويلات الإحصائية (Statistical transformations) التي تقوم بها حزمة ggplot2 خلف الكواليس عند إنشاء المخطط البياني. تُستخدم هذه التحويلات لحساب قيم جديدة لرسمها، مثل أطوال الأعمدة في مخطط الأعمدة أو الخطوط المنصفة في المخطط الصندوقي. ستتعلم أيضاً عن تعديلات المواضع (Position adjustments)، والتي تعدل كيفية عرض الأشكال الهندسية (geoms) في مخططاتك. أخيراً، سنقدم مقدمة موجزة عن أنظمة الإحداثيات (Coordinate systems).
لن نقوم بتغطية كل دالة وخيار لكل طبقة من هذه الطبقات، ولكننا سنأخذك في جولة عبر الوظائف الأكثر أهمية والأكثر استخداماً والتي توفرها حزمة ggplot2، بالإضافة إلى تعريفك بالحزم التي تمتد وتوسع من قدرات ggplot2.
9.1.1 المتطلبات المسبقة
يركز هذا الفصل بشكل أساسي على حزمة ggplot2. للوصول إلى مجموعات البيانات، وصفحات المساعدة، والدوال المستخدمة في هذا الفصل، قم بتحميل منظومة tidyverse عن طريق تشغيل هذا الكود:
9.2 جماليات الربط (Aesthetic mappings)
“تكمن القيمة العظمى للصورة عندما تجبرنا على ملاحظة ما لم نكن نتوقع رؤيته قط.” — جون توكي (John Tukey)
تذكر أن إطار البيانات mpg المرفق مع حزمة ggplot2 يحتوي على 234 مشاهدة لـ 38 طرازاً من طرازات السيارات.
mpg
#> # A tibble: 234 × 11
#> manufacturer model displ year cyl trans drv cty hwy fl
#> <chr> <chr> <dbl> <int> <int> <chr> <chr> <int> <int> <chr>
#> 1 audi a4 1.8 1999 4 auto(l5) f 18 29 p
#> 2 audi a4 1.8 1999 4 manual(m5) f 21 29 p
#> 3 audi a4 2 2008 4 manual(m6) f 20 31 p
#> 4 audi a4 2 2008 4 auto(av) f 21 30 p
#> 5 audi a4 2.8 1999 6 auto(l5) f 16 26 p
#> 6 audi a4 2.8 1999 6 manual(m5) f 18 26 p
#> # ℹ 228 more rows
#> # ℹ 1 more variable: class <chr>من بين المتغيرات الموجودة في mpg ما يلي:
displ: سعة محرك السيارة، باللتر. وهو متغير عددي (Numerical variable).hwy: كفاءة السيارة في استهلاك الوقود على الطرق السريعة، بالميل لكل جالون (mpg). السيارة ذات الكفاءة المنخفضة تستهلك وقوداً أكثر من السيارة ذات الكفاءة العالية عندما تقطعان نفس المسافة. وهو متغير عددي.class: نوع السيارة. وهو متغير فئوي (Categorical variable).
دعنا نبدأ بالتمثيل البصري للعلاقة بين displ و hwy لمختلف فئات السيارات class. يمكننا القيام بذلك باستخدام مخطط تشتت (scatterplot) حيث يتم ربط المتغيرات الرقمية بالخصائص الجمالية للمحورين x و y ويتم ربط المتغير الفئوي بخصوصية جمالية مثل اللون color أو الشكل shape.
# Left
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point()
# Right
ggplot(mpg, aes(x = displ, y = hwy, shape = class)) +
geom_point()
#> Warning: The shape palette can deal with a maximum of 6 discrete values because more
#> than 6 becomes difficult to discriminate
#> ℹ you have requested 7 values. Consider specifying shapes manually if you
#> need that many of them.
#> Warning: Removed 62 rows containing missing values or values outside the scale range
#> (`geom_point()`).

عندما يتم ربط المتغير class بجمالية الشكل shape، فإننا نحصل على تحذيرين:
1: يمكن لوحة أشكال الأشكال التعامل مع بحد أقصى 6 قيم منفصلة لأن أكثر من 6 يصبح من الصعب التمييز بينها؛ لديك 7. ضع في اعتبارك تحديد الأشكال يدوياً إذا كان لا بد من وجودها.
2: تم إزالة 62 صفاً تحتوي على قيم مفقودة (
geom_point()).
نظراً لأن ggplot2 ستستخدم ستة أشكال فقط في المرة الواحدة بشكل افتراضي، فإن المجموعات الإضافية لن يتم رسمها عندما تستخدم جمالية الشكل. والتحذير الثاني مرتبط بذلك – حيث توجد 62 سيارة من فئة SUV في مجموعة البيانات ولم يتم رسمها.
وبالمثل، يمكننا ربط المتغير class بجماليات الحجم size أو الشفافية alpha أيضاً، واللذين يتحكمان في حجم النقاط ودرجة شفافيتها على التوالي.
# Left
ggplot(mpg, aes(x = displ, y = hwy, size = class)) +
geom_point()
#> Warning: Using size for a discrete variable is not advised.
# Right
ggplot(mpg, aes(x = displ, y = hwy, alpha = class)) +
geom_point()
#> Warning: Using alpha for a discrete variable is not advised.

وينتج عن كلاهما تحذيرات أيضاً:
لا ينصح باستخدام الشفافية (alpha) لمتغير منفصل.
إن ربط متغير منفصل (فئوي) غير مرتب (class) بجمالية مرتبة (size أو alpha) ليس فكرة جيدة عموماً لأنه يوحي بوجود ترتيب أو رتبة لا وجود لها في الواقع.
بمجرد قيامك بربط الجمالية، تتولى ggplot2 الباقي. فهي تختار مقياساً معقولاً لاستخدامه مع الجمالية، وتقوم ببناء مفتاح رسم (Legend) يشرح الربط بين المستويات والقيم. بالنسبة لجماليات المحورين x و y، لا تقوم ggplot2 بإنشاء مفتاح رسم، ولكنها تنشئ خط محور مع علامات تدريج وتسمية (Label). يوفر خط المحور نفس المعلومات التي يوفرها مفتاح الرسم؛ فهو يشرح الربط بين المواقع والقيم.
يمكنك أيضاً تحديد الخصائص البصرية للشكل الهندسي يدوياً كـ وسيط داخل دالة الشكل الهندسي الخاصة بك (خارج دالة aes()) بدلاً من الاعتماد على ربط المتغيرات لتحديد المظهر. على سبيل المثال، يمكننا جعل جميع النقاط في مخططنا باللون الأزرق:
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(color = "blue")
هنا، لا ينقل اللون معلومات حول متغير ما، ولكنه يغير فقط المظهر الخارجي للمخطط. ستحتاج إلى اختيار قيمة منطقية لتلك الجمالية:
- اسم اللون كسلسلة نصية، على سبيل المثال،
color = "blue" - حجم النقطة بالملليمتر، على سبيل المثال،
size = 1 - شكل النقطة كرقم، على سبيل المثال،
shape = 1، كما هو موضح في الشكل 9.1.
color والتعبئة fill. الأشكال المجوفة (0-14) لها حدود يتم تحديدها بواسطة الجمالية color؛ الأشكال المصمتة (15-20) يتم تعبئتها بواسطة color؛ الأشكال المعبأة (21-25) لها حدود من color ويتم تعبئتها بواسطة الجمالية fill. تم ترتيب الأشكال للحفاظ على الأشكال المتشابهة متجاورة.
لقد ناقشنا حتى الآن الجماليات التي يمكننا ربطها أو تحديدها في مخطط التشتت، عند استخدام الشكل الهندسي للنقاط (point geom). يمكنك معرفة المزيد حول جميع جماليات الربط الممكنة في كتيب مواصفات الجماليات المتاح على الرابط https://ggplot2.tidyverse.org/articles/ggplot2-specs.html.
تعتمد الجماليات المحددة التي يمكنك استخدامها للمخطط على الشكل الهندسي الذي تستخدمه لتمثيل البيانات. تعتمد الجماليات المحدفي القسم التالي، سنغوص بعمق أكبر في الأشكال الهندسية .
9.2.1 تمارين
أنشئ مخططاً تشتتياً لـ
hwyمقابلdisplبحيث تكون النقاط عبارة عن مثلثات معبأة باللون الوردي.-
لماذا لم يؤدِ الكود التالي إلى ظهور مخطط بنقاط زرقاء؟
ggplot(mpg) + geom_point(aes(x = displ, y = hwy, color = "blue")) ماذا تفعل الجمالية
stroke؟ ومع أي الأشكال تعمل؟ (إرشاد: استخدم الأمر?geom_point).ماذا يحدث إذا قمت بربط جمالية بشيء آخر غير اسم المتغير، مثل
aes(color = displ < 5)؟ لاحظ أنه سيتعين عليك أيضاً تحديد المحورين x و y.
9.3 الأشكال الهندسية
ما وجه الشبه بين هذين المخططين؟


يحتوي كلا المخططين على نفس متغير x، ونفس متغير y، وكلاهما يصفان نفس البيانات. لكن المخططين ليسا متطابقين؛ حيث يستخدم كل مخطط كائناً هندسياً (Geometric object) مختلفاً - يُعرف اختصاراً بـ geom - لتمثيل البيانات. يستخدم المخطط الأيسر الشكل الهندسي للنقاط (point geom)، بينما يستخدم المخطط الأيمن الشكل الهندسي للمنحنيات الناعمة (smooth geom)، وهو خط ناعم يتم مواءمته وتوزينه بناءً على البيانات.
لتغيير الشكل الهندسي في مخططك، قم بتغيير دالة الـ geom التي تضيفها إلى ggplot(). على سبيل المثال، لإنشاء المخططات أعلاه، يمكنك استخدام الكود التالي:
# Left
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point()
# Right
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_smooth()
#> `geom_smooth()` using method = 'loess' and formula = 'y ~ x'تأخذ كل دالة geom في حزمة ggplot2 وسيطاً للربط mapping، إما أن يتم تعريفه محلياً (Locally) في طبقة الـ geom نفسها أو عالمياً (Globally) في طبقة ggplot(). ومع ذلك، لا تعمل كل جمالية مع كل geom؛ فقد تتمكن من تحديد شكل النقطة، لكنك لا تستطيع تحديد “شكل” الخط! إذا حاولت القيام بذلك، فإن ggplot2 ستتجاهل ربط تلك الجمالية بصمت دون إظهار خطأ. من ناحية أخرى، يمكنك تحديد نوع الخط (linetype) للشكل الهندسي الخطي. ستقوم الدالة geom_smooth() برسم خط مختلف، بنوع خط مختلف، لكل قيمة فريدة للمتغير الذي تربطه بنوع الخط.
# Left
ggplot(mpg, aes(x = displ, y = hwy, shape = drv)) +
geom_smooth()
# Right
ggplot(mpg, aes(x = displ, y = hwy, linetype = drv)) +
geom_smooth()

هنا، تقوم الدالة geom_smooth() بفصل السيارات إلى ثلاثة خطوط بناءً على قيمة المتغير drv الذي يصف نظام الدفع في السيارة. حيث يصف أحد الخطوط جميع النقاط التي لها القيمة 4 (دفع رباعي)، ويصف خط آخر جميع النقاط التي لها القيمة f (دفع أمامي)، ويصف الخط الأخير جميع النقاط التي لها القيمة r (دفع خلفي).
إذا كان هذا يبدو غريباً، فيمكننا جعله أكثر وضوحاً من خلال تراكب الخطوط فوق البيانات الخام ثم تلوين كل شيء وفقاً للمتغير drv.
ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
geom_point() +
geom_smooth(aes(linetype = drv))
لاحظ أن هذا المخطط يحتوي على شكلين هندسيين (two geoms) في نفس الرسم البياني.
تستخدم العديد من الأشكال الهندسية، مثل geom_smooth()، كائناً هندسياً واحداً لعرض صفوف متعددة من البيانات. بالنسبة لهذه الأشكال الهندسية، يمكنك ضبط جمالية المجموعة group على متغير فئوي لرسم كائنات متعددة؛ حيث ستقوم ggplot2 برسم كائن منفصل لكل قيمة فريدة لمتغير التجميع. عملياً، ستقوم ggplot2 بتجميع البيانات تلقائياً لهذه الأشكال الهندسية كلما قمت بربط جمالية بمتغير منفصل (كما في مثال linetype). ومن المناسب الاعتماد على هذه الميزة لأن جمالية group بمفردها لا تضيف مفتاح رسم أو ميزات تمييزية للأشكال الهندسية.
# Left
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_smooth()
# Middle
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_smooth(aes(group = drv))
# Right
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_smooth(aes(color = drv), show.legend = FALSE)


إذا وضعت روابط الجماليات داخل دالة geom معينة، فإن ggplot2 ستتعامل معها كروابط محلية (Local mappings) لتلك الطبقة فقط. وستستخدم هذه الروابط لتوسيع أو استبدال الروابط العالمية (Global mappings) لتلك الطبقة دون غيرها. وهذا يجعل من الممكن عرض جماليات مختلفة في طبقات مختلفة.
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(aes(color = class)) +
geom_smooth()
يمكنك استخدام نفس الفكرة لتحديد بيانات data مختلفة لكل طبقة. هنا، نستخدم نقاطاً حمراء بالإضافة إلى دوائر مفتوحة لتسليط الضوء على السيارات ذات المقعدين (two-seater). يحل وسيط البيانات المحلي في دالة geom_point() محل وسيط البيانات العالمي في دالة ggplot() لتلك الطبقة فقط.
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
geom_point(
data = mpg |> filter(class == "2seater"),
color = "red"
) +
geom_point(
data = mpg |> filter(class == "2seater"),
shape = "circle open", size = 3, color = "red"
)
الأشكال الهندسية هي لبنات البناء الأساسية في ggplot2. يمكنك تحويل مظهر مخططك بالكامل عن طريق تغيير الـ geom الخاص به، ويمكن للأشكال الهندسية المختلفة أن تكشف عن ميزات مختلفة لبياناتك. على سبيل المثال، يكشف المدرج التكراري (histogram) ومخطط الكثافة (density plot) أدناه أن توزيع مسافات الطرق السريعة ثنائي النمط (bimodal) وملتوي نحو اليمين، بينما يكشف المخطط الصندوقي (boxplot) عن وجود قيمتين متطرفتين محتملتين.
# Left
ggplot(mpg, aes(x = hwy)) +
geom_histogram(binwidth = 2)
# Middle
ggplot(mpg, aes(x = hwy)) +
geom_density()
# Right
ggplot(mpg, aes(x = hwy)) +
geom_boxplot()


توفر حزمة ggplot2 أكثر من 40 شكلاً هندسياً (geom)، ولكنها لا تغطي جميع المخططات الممكنة التي يمكن للمرء إنشاؤها. إذا كنت بحاجة إلى geom مختلف، نوصي بالبحث في الحزم الامتدادية أولاً لمعرفة ما إذا كان شخص آخر قد قام بتنفيذه بالفعل (راجع الرابط https://exts.ggplot2.tidyverse.org/gallery/ للاطلاع على عينات منها). على سبيل المثال، تُعد حزمة (https://wilkelab.org/ggridges) ggridges مفيدة لإنشاء مخططات الكثافة المتراكبة (ridgeline plots)، والتي يمكن أن تكون مفيدة لتصور كثافة متغير عددي لمستويات مختلفة من متغير فئوي. في المخطط التالي، لم نستخدم فحسب شكلاً هندسياً جديداً (geom_density_ridges())، بل قمنا أيضاً بربط نفس المتغير بجماليات متعددة (ربط drv بالمحور y والتعبئة fill واللون color) بالإضافة إلى تحديد قيمة ثابتة للشفافية (alpha = 0.5) لجعل منحنيات الكثافة شفافة.
library(ggridges)
ggplot(mpg, aes(x = hwy, y = drv, fill = drv, color = drv)) +
geom_density_ridges(alpha = 0.5, show.legend = FALSE)
#> Picking joint bandwidth of 1.28
إن أفضل مكان للحصول على نظرة شاملة لجميع الأشكال الهندسية التي تقدمها ggplot2، بالإضافة إلى جميع الدوال الموجودة في الحزمة، هو صفحة المراجع الرسمية: https://ggplot2.tidyverse.org/reference. ولمعرفة المزيد حول أي geom بمفرده، استخدم صفحة المساعدة الخاصة به (على سبيل المثال ?geom_smooth).
9.3.1 تمارين
ما هو الشكل الهندسي (geom) الذي ستستخدمه لرسم مخطط خطي (line chart)؟ ومخطط صندوقي (boxplot)؟ ومدرج تكراري (histogram)؟ ومخطط مساحي (area chart)؟
-
في مرحلة سابقة من هذا الفصل، استخدمنا الوسيط
show.legendدون شرحه:ggplot(mpg, aes(x = displ, y = hwy)) + geom_smooth(aes(color = drv), show.legend = FALSE)ماذا يفعل الأمر
show.legend = FALSEهنا؟ وماذا يحدث إذا قمت بحذفه؟ ولماذا تعتقد أننا استخدمناه في جزء سابق؟ ماذا يفعل الوسيط
seداخل الدالةgeom_smooth()؟-
أعد كتابة كود R اللازم لتوليد المخططات البيانية التالية. لاحظ أنه أينما تم استخدام متغير فئوي في المخطط، فإنه يكون المتغير
drv.





9.4 الأوجه (Facets)
في الفصل 1، تعلمت عن تقسيم المخططات إلى أوجه باستخدام الدالة facet_wrap()، والتي تقسم المخطط الرئيسي إلى مخططات فرعية تعرض كل منها جزءاً مستقطعاً من البيانات بناءً على متغير فئوي.
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~cyl)
لتقسيم مخططك إلى أوجه بناءً على توليفة من متغيرين، انتقل من استخدام facet_wrap() إلى الدالة facet_grid(). الوسيط الأول للدالة facet_grid() هو أيضاً صيغة رياضية (formula)، ولكنه الآن عبارة عن صيغة ثنائية الجانب: rows ~ cols (الصفوف ~ الأعمدة).
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_grid(drv ~ cyl)
بشكل افتراضي، تشترك جميع الأوجه في نفس المقياس والنطاق للمحورين الأفقي x والعمودي y. هذا الأمر مفيد جداً عندما تريد مقارنة البيانات عبر الأوجه المختلفة، ولكنه قد يكون قيداً عندما تريد تصور العلاقة داخل كل وجه بشكل أفضل. إن ضبط وسيط المقاييس scales في دالة تقسيم الأوجه على القيمة "free_x" سيسمح بمقاييس مختلفة لمحور x عبر الأعمدة، وتحديد "free_y" سيسمح بمقاييس مختلفة لمحور y عبر الصفوف، بينما تسمح القيمة "free" بالاثنين معاً.
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_grid(drv ~ cyl, scales = "free")
9.4.1 تمارين
ماذا يحدث إذا قمت بتقسيم الأوجه بناءً على متغير متصل (Continuous variable)؟
-
ماذا تعني الخلايا الفارغة في المخطط أعلاه الذي استخدمنا فيه
facet_grid(drv ~ cyl)؟ شغّل الكود التالي، وكيف ترتبط بالنتيجة في المخطط؟ggplot(mpg) + geom_point(aes(x = drv, y = cyl)) -
ما هي المخططات التي ينتجها الكود التالي؟ وماذا تفعل النقطة
.هنا؟ggplot(mpg) + geom_point(aes(x = displ, y = hwy)) + facet_grid(drv ~ .) ggplot(mpg) + geom_point(aes(x = displ, y = hwy)) + facet_grid(. ~ cyl) -
خذ المخطط الأول المقسم إلى أوجه في هذا القسم:
ggplot(mpg) + geom_point(aes(x = displ, y = hwy)) + facet_wrap(~ cyl, nrow = 2)ما هي مزايا استخدام تقسيم الأوجه بدلاً من جمالية اللون؟ وما هي العيوب؟ وكيف يمكن أن يتغير هذا التوازن إذا كان لديك مجموعة بيانات أكبر بكثير؟
اقرأ صفحة المساعدة الخاصة بالدالة
?facet_wrap. ماذا يفعل الوسيطnrow؟ وماذا يفعلncol؟ وما هي الخيارات الأخرى التي تتحكم في تخطيط اللوحات الفردية؟ ولماذا لا تحتوي الدالةfacet_grid()على وسيطيnrowوncol؟-
أي من المخططات التالية يسهل مقارنة سعة المحرك (
displ) عبر السيارات ذات أنظمة الدفع المختلفة؟ وماذا يقول هذا عن متى يجب وضع متغير تقسيم الأوجه عبر الصفوف أو الأعمدة؟ggplot(mpg, aes(x = displ)) + geom_histogram() + facet_grid(drv ~ .) ggplot(mpg, aes(x = displ)) + geom_histogram() + facet_grid(. ~ drv) -
أعد إنشاء المخطط التالي باستخدام الدالة
facet_wrap()بدلاً منfacet_grid(). كيف تتغير مواضع تسميات الأوجه؟ggplot(mpg) + geom_point(aes(x = displ, y = hwy)) + facet_grid(drv ~ .)
9.5 التحويلات الإحصائية (Statistical transformations)
لنأخذ في الاعتبار مخططاً عمودياً أساسياً، يتم رسمه باستخدام الدالة geom_bar() أو geom_col(). يعرض المخطط التالي العدد الإجمالي للألماس في مجموعة بيانات diamonds، مقسمة حسب جودة القطع cut. مجموعة بيانات diamonds مدمجة في حزمة ggplot2 وتحتوي على معلومات حول ما يقرب من 54,000 قطعة ألماس، بما في ذلك السعر price، والوزن بالقيراط carat، واللون color، والنقاء clarity، وجودة القطع cut لكل ألماسة. يظهر المخطط أن هناك عدداً أكبر من الألماس المتاح بقطع ذي جودة عالية مقارنة بالقطع ذي الجودة المنخفضة.
يعرض المخطط على المحور الأفقي المتغير cut، وهو متغير مستمد مباشرة من مجموعة البيانات diamonds. بينما يعرض على المحور العمودي التكرار أو العدد (count)، ولكن التكرار ليس متغيراً في diamonds! فمن أين أتى هذا التكرار؟ العديد من الرسومات البيانية، مثل مخططات التشتت، تقوم برسم القيم الخام لمجموعة البيانات الخاصة بك. بينما تقوم رسومات بيانية أخرى، مثل مخططات الأعمدة، بحساب قيم جديدة لرسمها:
تقوم مخططات الأعمدة (Bar charts)، والمدرجات التكرارية (histograms)، والمضلعات التكرارية (frequency polygons) بتجميع بياناتك في فئات ثم رسم تكرارات هذه الفئات، أي عدد النقاط التي تقع في كل فئة.
تقوم منحنيات المواءمة والتنعيم (Smoothers) بمواءمة نموذج إحصائي مع بياناتك ثم رسم التنبؤات الناتجة عن هذا النموذج.
تقوم المخططات الصندوقية (Boxplots) بحساب ملخص الأعداد الخمسة (five-number summary) للتوزيع ثم تعرض هذا الملخص في شكل صندوق منسق خصيصاً.
تُسمى الخوارزمية المستخدمة لحساب القيم الجديدة للمخطط البياني بـ stat، وهي اختصار للتحويل الإحصائي (statistical transformation). يوضح الشكل 9.2 كيفية عمل هذه العملية مع الدالة geom_bar().
يمكنك معرفة التحويل الإحصائي (stat) الذي يستخدمه الشكل الهندسي (geom) من خلال فحص القيمة الافتراضية لوسيط stat. على سبيل المثال، توضح صفحة المساعدة ?geom_bar أن القيمة الافتراضية لـ stat هي "count"، مما يعني أن الدالة geom_bar() تستخدم الدالة stat_count(). تم توثيق الدالة stat_count() في نفس الصفحة الخاصة بـ geom_bar(). إذا قمت بالتمرير لأسفل، فإن القسم المسمى (المتغيرات المحسوبة) “Variables computed” يوضح أنها تحسب متغيرين جديدين: count (التكرار) و prop (النسبة التناسبية).
لكل شكل هندسي (geom) تحويل إحصائي (stat) افتراضي؛ ولكل تحويل إحصائي شكل هندسي افتراضي. هذا يعني أنه يمكنك عادةً استخدام الأشكال الهندسية دون القلق بشأن التحويل الإحصائي الكامن وراءها. ومع ذلك، هناك ثلاثة أسباب قد تجعلك تحتاج إلى استخدام التحويل الإحصائي بشكل صريح:
-
قد ترغب في إلغاء التحويل الإحصائي الافتراضي واستبداله. في الكود أدناه، نقوم بتغيير الـ stat للدالة
geom_bar()من count (الافتراضي) إلى identity. يتيح لنا هذا ربط ارتفاع الأعمدة بالقيم الخام لمتغير y مباشرة. -
قد ترغب في استبدال الربط الافتراضي من المتغيرات المحولة إلى الجماليات. على سبيل المثال، قد ترغب في عرض مخطط أعمدة للنسب التناسبية بدلاً من التكرارات:
ggplot(diamonds, aes(x = cut, y = after_stat(prop), group = 1)) + geom_bar()
للعثور على المتغيرات المحتملة التي يمكن حسابها بواسطة التحويل الإحصائي، ابحث عن القسم المعنون “computed variables” في صفحة المساعدة للدالة
geom_bar(). -
قد ترغب في توجيه اهتمام أكبر إلى التحويل الإحصائي في كودك البرمجي. على سبيل المثال، يمكنك استخدام الدالة
stat_summary()، والتي تلخص قيم y لكل قيمة فريدة من قيم x، لجلب الانتباه إلى الملخص الإحصائي الذي تقوم بحسابه:ggplot(diamonds) + stat_summary( aes(x = cut, y = depth), fun.min = min, fun.max = max, fun = median )
توفر حزمة ggplot2 أكثر من 20 تحويلاً إحصائياً (stats) لتستخدمها. ولكل تحويل إحصائي دالة خاصة به، لذا يمكنك الحصول على المساعدة بالطريقة المعتادة، مثل تشغيل الأمر ?stat_bin.
9.5.1 تمارين
ما هو الشكل الهندسي الافتراضي المرتبط بالدالة
stat_summary()؟ كيف يمكنك إعادة كتابة المخطط السابق لاستخدام دالة الـ geom تلك بدلاً من دالة الـ stat؟ماذا تفعل الدالة
geom_col()؟ وكيف تختلف عن الدالةgeom_bar()؟تأتي معظم الأشكال الهندسية (geoms) والتحويلات الإحصائية (stats) في أزواج تُستخدم معاً تقريباً في كل الأوقات. أنشئ قائمة بجميع هذه الأزواج. ما الذي يجمع بينها؟ (إرشاد: اقرأ التوثيقات وصفحات المساعدة).
ما هي المتغيرات التي تحسبها الدالة
stat_smooth()؟ وما هي الوسائط التي تتحكم في سلوكها؟-
في مخطط أعمدة النسب التناسبية الخاص بنا، احتجنا إلى ضبط وسيط التجميع على
group = 1. لماذا؟ وبعبارة أخرى، ما هي المشكلة في هذين المخططين البيانيين؟ggplot(diamonds, aes(x = cut, y = after_stat(prop))) + geom_bar() ggplot(diamonds, aes(x = cut, fill = color, y = after_stat(prop))) + geom_bar()
9.6 تعديلات المواضع (Position adjustments)
هناك سحر آخر يرتبط بمخططات الأعمدة. يمكنك تلوين مخطط الأعمدة باستخدام إما جمالية اللون color، أو، وهو الأكثر فائدة، جمالية التعبئة fill:


لاحظ ماذا يحدث إذا قمت بربط جمالية التعبئة بمتغير آخر، مثل فئة السيارة class: يتم تكديس الأعمدة تلقائياً (stacked). ويمثل كل مستطيل ملون توليفة من متغير نظام الدفع drv وفئة السيارة class.
يتم إجراء هذا التكديس تلقائياً باستخدام تعديل الموضع (position adjustment) المحدد بواسطة وسيط الموضع position. إذا كنت لا تريد مخطط أعمدة مكدساً، يمكنك استخدام أحد الخيارات الثلاثة الأخرى: "identity" أو "dodge" أو "fill".
-
يضع الأمر
position = "identity"كل كائن في المكان الذي يقع فيه بالضبط في سياق الرسم البياني. وهذا ليس مفيداً جداً للأعمدة، لأنه يؤدي إلى تداخلها وتغطية بعضها البعض. لرؤية هذا التداخل، نحتاج إما إلى جعل الأعمدة شفافة قليلاً عن طريق ضبط الشفافيةalphaعلى قيمة صغيرة، أو جعلها شفافة تماماً عن طريق تعيين التعبئة كقيمة فارغةfill = NA.

يُعد تعديل الموضع المتمثل في الهوية (identity position adjustment) أكثر فائدة للأشكال الهندسية ثنائية الأبعاد، مثل النقاط، حيث يكون هو الخيار الافتراضي لها.
يعمل الأمر
position = "fill"بشكل يشبه التكديس، ولكنه يجعل كل مجموعة من الأعمدة المكدسة بنفس الارتفاع تماماً. وهذا يسهل من عملية مقارنة النسب التناسبية عبر المجموعات المختلفة.-
يضع الأمر
position = "dodge"الكائنات المتداخلة جنباً إلى جنب مباشرة. وهذا يسهل من عملية مقارنة القيم الفردية.
هناك نوع آخر من التعديلات لا يفيد في مخططات الأعمدة، ولكنه قد يكون مفيداً جداً لمخططات التشتت. تذكر مخططنا التشتتي الأول؛ هل لاحظت أن المخطط يعرض 126 نقطة فقط، على الرغم من وجود 234 مشاهدة في مجموعة البيانات؟

القيم الكامنة لمتغيري hwy و displ مقربة، لذا تظهر النقاط على شبكة منتظمة ويتداخل العديد منها فوق بعضها البعض. تُعرف هذه المشكلة باسم التطابق المفرط للرسم (Overplotting). يجعل هذا الترتيب من الصعب رؤية توزيع البيانات؛ فهل نقاط البيانات موزعة بالتساوي في جميع أنحاء المخطط، أم أن هناك توليفة خاصة واحدة من hwy و displ تحتوي على 109 قيم؟
يمكنك تجنب هذا التراصف الشبكي عن طريق ضبط تعديل الموضع على القيمة "jitter" (الارتعاش أو التشتيت). يضيف الأمر position = "jitter" مقداراً صغيراً من الضوضاء العشوائية لكل نقطة؛ يؤدي هذا إلى تشتيت النقاط وتباعدها لأنه من غير المحتمل أن تحصل أي نقطتين على نفس المقدار من الضوضاء العشوائية تماماً.
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(position = "jitter")
قد يبدو إدخال العشوائية طريقة غريبة لتحسين مخططك البياني، ولكن بينما يجعل المخطط أقل دقة عند المقاييس الصغيرة، فإنه يجعله أكثر كشفاً وإيضاحاً عند المقاييس الكبيرة. ونظراً لأن هذه العملية مفيدة للغاية، فإن ggplot2 تأتي باختصار للدالة geom_point(position = "jitter") وهو: geom_jitter().
لمعرفة المزيد حول تعديلات المواضع، يمكنك البحث في صفحات المساعدة المرتبطة بكل تعديل: ?position_dodge و ?position_fill و ?position_identity و ?position_jitter و ?position_stack.
9.6.1 تمارين
-
ما هي المشكلة في المخطط البياني التالي؟ وكيف يمكنك تحسينه؟
ggplot(mpg, aes(x = cty, y = hwy)) + geom_point() -
ما الفرق -إن وُجد- بين هذين المخططين البيانيين؟ ولماذا؟
ggplot(mpg, aes(x = displ, y = hwy)) + geom_point() ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(position = "identity") ما هي المعلمات (parameters) في دالة
geom_jitter()التي تتحكم في مقدار التشتيت والارتعاش؟قارن وقابل بين الدالتين
geom_jitter()وgeom_count().ما هو تعديل الموضع الافتراضي للدالة
geom_boxplot()؟ أنشئ تصوراً بيانياً لمجموعة بياناتmpgيوضح ذلك عملياً.
9.7 أنظمة الإحداثيات (Coordinate systems)
ربما تكون أنظمة الإحداثيات هي الجزء الأكثر تعقيداً في ggplot2. نظام الإحداثيات الافتراضي هو نظام الإحداثيات الديكارتية (Cartesian coordinate system) حيث يعمل موقعا x و y بشكل مستقل لتحديد موقع كل نقطة. وهناك نظاما إحداثيات آخران يفيدان في بعض الأحيان:
-
يقوم الأمر
coord_quickmap()بضبط نسبة الأبعاد (aspect ratio) بشكل صحيح للخرائط الجغرافية. وهذا أمر مهم للغاية إذا كنت ترسم بيانات مكانية (spatial data) باستخدام ggplot2. ليس لدينا مساحة كافية لمناقشة الخرائط في هذا الكتاب، ولكن يمكنك معرفة المزيد في فصل الخرائط من كتاب ggplot2: Elegant graphics for data analysis.nz <- map_data("nz") ggplot(nz, aes(x = long, y = lat, group = group)) + geom_polygon(fill = "white", color = "black") ggplot(nz, aes(x = long, y = lat, group = group)) + geom_polygon(fill = "white", color = "black") + coord_quickmap()

-
تستخدم الدالة
coord_polar()الإحداثيات القطبية (polar coordinates). تكشف الإحداثيات القطبية عن صلة ربط مثيرة للاهتمام بين مخطط الأعمدة ومخطط كوكسكومب (Coxcomb chart).bar <- ggplot(data = diamonds) + geom_bar( mapping = aes(x = clarity, fill = clarity), show.legend = FALSE, width = 1 ) + theme(aspect.ratio = 1) bar + coord_flip() bar + coord_polar()

9.7.1 تمارين
حوّل مخطط أعمدة مكدس إلى مخطط دائري (pie chart) باستخدام الدالة
coord_polar().ما الفرق بين
coord_quickmap()وcoord_map()؟-
ماذا يخبرك المخطط البياني التالي عن العلاقة بين استهلاك الوقود داخل المدينة وعلى الطرق السريعة؟ ولماذا يُعد الأمر
coord_fixed()مهماً؟ وماذا تفعل الدالةgeom_abline()؟ggplot(data = mpg, mapping = aes(x = cty, y = hwy)) + geom_point() + geom_abline() + coord_fixed()
9.8 القواعد الطبقية للرسومات
يمكننا التوسع في قالب الرسم البياني الذي تعلمته في قسم 1.3 عن طريق إضافة تعديلات المواضع، والتحويلات الإحصائية، وأنظمة الإحداثيات، وتقسيم الأوجه:
ggplot(data = <DATA>) +
<GEOM_FUNCTION>(
mapping = aes(<MAPPINGS>),
stat = <STAT>,
position = <POSITION>
) +
<COORDINATE_FUNCTION> +
<FACET_FUNCTION>
يأخذ قالبنا الجديد سبعة معلمات، وهي الكلمات الموجودة بين قوسي زاوية في القالب. عملياً، نادراً ما تحتاج إلى توفير المعلمات السبعة جميعها لإنشاء رسم بياني لأن ggplot2 ستوفر قيمًا افتراضية مفيدة لكل شيء باستثناء البيانات، وروابط الجماليات، ودالة الشكل الهندسي (geom).
تشكل المعلمات السبعة في القالب قواعد الرسومات (grammar of graphics)، وهو نظام رسمي لبناء المخططات البيانية. وتعتمد قواعد الرسومات على رؤية معمقة تفيد بأنه يمكنك وصف أي مخطط بياني بشكل فريد كمزيج من مجموعة بيانات، وشكل هندسي (geom)، ومجموعة من روابط الجماليات، وتحويل إحصائي (stat)، وتعديل للموضع، ونظام إحداثيات، ومخطط لتقسيم الأوجه، ومظهر عام (theme).
لمعرفة كيف يعمل هذا، فكر في كيفية بناء مخطط أساسي من الصفر: يمكنك البدء بمجموعة بيانات ثم تحويلها إلى المعلومات التي تريد عرضها (باستخدام تحويل إحصائي). بعد ذلك، يمكنك اختيار كائن هندسي لتمثيل كل مشاهدة في البيانات المحولة. ويمكنك بعد ذلك استخدام الخصائص البصرية للأشكال الهندسية لتمثيل المتغيرات في البيانات، حيث تقوم بربط قيم كل متغير بمستويات الجمالية. تم توضيح هذه الخطوات في الشكل 9.3. ثم تختار نظام إحداثيات لوضع الأشكال الهندسية بداخله، مستخدماً موقع الكائنات (وهو في حد ذاته خاصية جمالية) لعرض قيم متغيري x و y.
عند هذه النقطة، سيكون لديك مخطط بياني كامل، ولكن يمكنك إجراء المزيد من الضبط لمواضع الأشكال الهندسية داخل نظام الإحداثيات (تعديل الموضع) أو تقسيم المخطط إلى مخططات فرعية (تقسيم الأوجه). ويمكنك أيضاً توسيع المخطط عن طريق إضافة طبقة إضافية واحدة أو أكثر، حيث تستخدم كل طبقة إضافية مجموعة بيانات، وشكلاً هندسياً، ومجموعة من روابط الجماليات، وتحويلاً إحصائياً، وتعديلاً للموضع.
يمكنك استخدام هذه الطريقة لبناء أي مخطط بياني تتخيله. وبعبارة أخرى، يمكنك استخدام قالب الكود الذي تعلمته في هذا الفصل لبناء مئات الآلاف من المخططات البيانية الفريدة.
إذا كنت ترغب في معرفة المزيد عن الأسس النظرية الكامنة وراء حزمة ggplot2، فقد تستمتع بقراءة ورقة البحث العلمية “The Layered Grammar of Graphics”، والتي تصف نظرية ggplot2 بالتفصيل.
9.9 ملخص
تعلمت في هذا الفصل القواعد الطبقية للرسومات بدءاً من الجماليات والأشكال الهندسية لبناء مخطط بسيط، وتقسيم الأوجه لتقسيم المخطط إلى مجموعات فرعية، والتحويلات الإحصائية لفهم كيفية حساب الأشكال الهندسية، وتعديلات المواضع للتحكم في التفاصيل الدقيقة للموقع عندما تتداخل الأشكال الهندسية بخلاف ذلك، وأنظمة الإحداثيات التي تسمح لك بتغيير المعنى الجوهري للمحورين x و y. وهناك طبقة واحدة لم نتطرق إليها بعد وهي المظهر العام (theme)، والتي سنقدمها في قسم 11.5.
هناك موردان مفيدان للغاية للحصول على نظرة عامة على وظائف ggplot2 الكاملة وهما الورقة المرجعية السريعة الخاصة بـ ggplot2 (والتي يمكنك العثور عليها على الرابط https://posit.co/resources/cheatsheets) والموقع الإلكتروني للحزمة (https://ggplot2.tidyverse.org).
من الدروس المهمة التي يجب أن تستخلصها من هذا الفصل هو أنه عندما تشعر بالحاجة إلى شكل هندسي (geom) لا توفره ggplot2، فمن الجيد دائماً البحث عما إذا كان شخص آخر قد حل مشكلتك بالفعل عن طريق إنشاء حزمة امتدادية لـ ggplot2 تقدم ذلك الـ geom.




