{ "nbformat": 4, "nbformat_minor": 2, "metadata": { "colab": { "name": "lesson_2-R.ipynb", "provenance": [], "collapsed_sections": [], "toc_visible": true }, "kernelspec": { "name": "ir", "display_name": "R" }, "language_info": { "name": "R" }, "coopTranslator": { "original_hash": "f3c335f9940cfd76528b3ef918b9b342", "translation_date": "2025-08-29T14:59:43+00:00", "source_file": "2-Regression/2-Data/solution/R/lesson_2-R.ipynb", "language_code": "ar" } }, "cells": [ { "cell_type": "markdown", "source": [ "# بناء نموذج الانحدار: إعداد البيانات وتصويرها\n", "\n", "## **الانحدار الخطي للقرع - الدرس الثاني**\n", "#### المقدمة\n", "\n", "الآن بعد أن أصبحت مجهزًا بالأدوات اللازمة لبدء بناء نماذج تعلم الآلة باستخدام Tidymodels وTidyverse، أصبحت جاهزًا لبدء طرح الأسئلة على بياناتك. أثناء العمل مع البيانات وتطبيق حلول تعلم الآلة، من المهم جدًا فهم كيفية طرح السؤال الصحيح لفتح إمكانيات مجموعة البيانات الخاصة بك بشكل صحيح.\n", "\n", "في هذا الدرس، ستتعلم:\n", "\n", "- كيفية إعداد بياناتك لبناء النماذج.\n", "\n", "- كيفية استخدام `ggplot2` لتصور البيانات.\n", "\n", "السؤال الذي تحتاج إلى الإجابة عليه سيحدد نوع خوارزميات تعلم الآلة التي ستستخدمها. كما أن جودة الإجابة التي تحصل عليها تعتمد بشكل كبير على طبيعة بياناتك.\n", "\n", "دعونا نرى ذلك من خلال تمرين عملي.\n", "\n", "
\n",
" \n",
"
\n",
"\n",
"> تذكير سريع: مشغل الأنابيب (`%>%`) ينفذ العمليات بتسلسل منطقي عن طريق تمرير كائن إلى الأمام داخل دالة أو تعبير استدعاء. يمكنك التفكير في مشغل الأنابيب كأنه يقول \"ثم\" في الكود الخاص بك.\n"
],
"metadata": {
"id": "REWcIv9yX29v"
}
},
{
"cell_type": "markdown",
"source": [
"## 2. التحقق من البيانات المفقودة\n",
"\n",
"أحد أكثر المشاكل شيوعًا التي يواجهها علماء البيانات هي البيانات غير المكتملة أو المفقودة. يمثل R القيم المفقودة أو غير المعروفة باستخدام قيمة خاصة: `NA` (غير متوفرة).\n",
"\n",
"كيف يمكننا معرفة ما إذا كان إطار البيانات يحتوي على قيم مفقودة؟\n",
"
\n",
"- إحدى الطرق المباشرة هي استخدام وظيفة R الأساسية `anyNA` التي تُرجع الكائنات المنطقية `TRUE` أو `FALSE`.\n"
],
"metadata": {
"id": "Zxfb3AM5YbUe"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"pumpkins %>% \n",
" anyNA()"
],
"outputs": [],
"metadata": {
"id": "G--DQutAYltj"
}
},
{
"cell_type": "markdown",
"source": [
"هناك بعض البيانات المفقودة! هذه نقطة جيدة للبدء.\n",
"\n",
"- طريقة أخرى هي استخدام الدالة `is.na()` التي تشير إلى العناصر المفقودة في الأعمدة الفردية باستخدام القيمة المنطقية `TRUE`.\n"
],
"metadata": {
"id": "mU-7-SB6YokF"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"pumpkins %>% \n",
" is.na() %>% \n",
" head(n = 7)"
],
"outputs": [],
"metadata": {
"id": "W-DxDOR4YxSW"
}
},
{
"cell_type": "markdown",
"source": [
"حسنًا، لقد أنجزت المهمة ولكن مع إطار بيانات كبير مثل هذا، سيكون من غير الفعّال ومن المستحيل عمليًا مراجعة جميع الصفوف والأعمدة بشكل فردي 😴.\n",
"\n",
"- طريقة أكثر سهولة ستكون حساب مجموع القيم المفقودة لكل عمود:\n"
],
"metadata": {
"id": "xUWxipKYY0o7"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"pumpkins %>% \n",
" is.na() %>% \n",
" colSums()"
],
"outputs": [],
"metadata": {
"id": "ZRBWV6P9ZArL"
}
},
{
"cell_type": "markdown",
"source": [
"أفضل بكثير! هناك بيانات مفقودة، ولكن ربما لن تكون مهمة لهذه المهمة. دعونا نرى ما ستكشفه المزيد من التحليلات.\n",
"\n",
"> بالإضافة إلى المجموعات الرائعة من الحزم والوظائف، يتميز R بتوثيق جيد جدًا. على سبيل المثال، استخدم `help(colSums)` أو `?colSums` لمعرفة المزيد عن الوظيفة.\n"
],
"metadata": {
"id": "9gv-crB6ZD1Y"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. Dplyr: قواعد معالجة البيانات\n",
"\n",
"
\n",
" \n",
"
\n"
],
"metadata": {
"id": "i5o33MQBZWWw"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::select()\n",
"\n",
"`select()` هي دالة في حزمة `dplyr` تساعدك على اختيار الأعمدة التي تريد الاحتفاظ بها أو استبعادها.\n",
"\n",
"لجعل إطار البيانات الخاص بك أسهل في التعامل، قم بحذف بعض الأعمدة باستخدام `select()`، مع الاحتفاظ فقط بالأعمدة التي تحتاجها.\n",
"\n",
"على سبيل المثال، في هذا التمرين، تحليلنا سيتضمن الأعمدة `Package`، `Low Price`، `High Price` و `Date`. دعنا نختار هذه الأعمدة.\n"
],
"metadata": {
"id": "x3VGMAGBZiUr"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Select desired columns\n",
"pumpkins <- pumpkins %>% \n",
" select(Package, `Low Price`, `High Price`, Date)\n",
"\n",
"\n",
"# Print data set\n",
"pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "F_FgxQnVZnM0"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::mutate()\n",
"\n",
"`mutate()` هي دالة في حزمة `dplyr` تساعدك على إنشاء أو تعديل الأعمدة، مع الاحتفاظ بالأعمدة الموجودة.\n",
"\n",
"الهيكل العام لدالة `mutate` هو:\n",
"\n",
"`data %>% mutate(new_column_name = what_it_contains)`\n",
"\n",
"لنقم بتجربة `mutate` باستخدام العمود `Date` من خلال تنفيذ العمليات التالية:\n",
"\n",
"1. تحويل التواريخ (التي هي حالياً من نوع نصي) إلى صيغة شهر (هذه تواريخ أمريكية، لذا الصيغة هي `MM/DD/YYYY`).\n",
"\n",
"2. استخراج الشهر من التواريخ إلى عمود جديد.\n",
"\n",
"في لغة R، تجعل الحزمة [lubridate](https://lubridate.tidyverse.org/) العمل مع بيانات التاريخ والوقت أسهل. لذا، دعونا نستخدم `dplyr::mutate()`، و`lubridate::mdy()`، و`lubridate::month()` لنرى كيف يمكن تحقيق الأهداف المذكورة أعلاه. يمكننا حذف عمود `Date` لأننا لن نحتاجه مرة أخرى في العمليات اللاحقة.\n"
],
"metadata": {
"id": "2KKo0Ed9Z1VB"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load lubridate\n",
"library(lubridate)\n",
"\n",
"pumpkins <- pumpkins %>% \n",
" # Convert the Date column to a date object\n",
" mutate(Date = mdy(Date)) %>% \n",
" # Extract month from Date\n",
" mutate(Month = month(Date)) %>% \n",
" # Drop Date column\n",
" select(-Date)\n",
"\n",
"# View the first few rows\n",
"pumpkins %>% \n",
" slice_head(n = 7)"
],
"outputs": [],
"metadata": {
"id": "5joszIVSZ6xe"
}
},
{
"cell_type": "markdown",
"source": [
"واو! 🤩\n",
"\n",
"الآن، دعونا ننشئ عمودًا جديدًا باسم `Price`، والذي يمثل متوسط سعر اليقطين. بعد ذلك، سنأخذ متوسط عمودي `Low Price` و`High Price` لملء العمود الجديد `Price`.\n"
],
"metadata": {
"id": "nIgLjNMCZ-6Y"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Create a new column Price\n",
"pumpkins <- pumpkins %>% \n",
" mutate(Price = (`Low Price` + `High Price`)/2)\n",
"\n",
"# View the first few rows of the data\n",
"pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "Zo0BsqqtaJw2"
}
},
{
"cell_type": "markdown",
"source": [
"نعم!💪\n",
"\n",
"\"لكن انتظر!\" ستقول بعد تصفح مجموعة البيانات بالكامل باستخدام `View(pumpkins)`, \"هناك شيء غريب هنا!\"🤔\n",
"\n",
"إذا نظرت إلى عمود `Package`, ستجد أن القرع يُباع بتكوينات مختلفة. بعضها يُباع بمقياس `1 1/9 bushel`, وبعضها بمقياس `1/2 bushel`, وبعضها لكل قرع، وبعضها لكل رطل، وبعضها في صناديق كبيرة بأحجام مختلفة.\n",
"\n",
"دعونا نتحقق من ذلك:\n"
],
"metadata": {
"id": "p77WZr-9aQAR"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Verify the distinct observations in Package column\n",
"pumpkins %>% \n",
" distinct(Package)"
],
"outputs": [],
"metadata": {
"id": "XISGfh0IaUy6"
}
},
{
"cell_type": "markdown",
"source": [
"رائع!👏\n",
"\n",
"يبدو أن قياس وزن القرع بشكل متسق أمر صعب للغاية، لذا دعونا نقوم بتصفية القرع عن طريق اختيار فقط القرع الذي يحتوي على الكلمة *bushel* في عمود `Package` ووضع ذلك في إطار بيانات جديد `new_pumpkins`. \n"
],
"metadata": {
"id": "7sMjiVujaZxY"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::filter() و stringr::str_detect()\n",
"\n",
"[`dplyr::filter()`](https://dplyr.tidyverse.org/reference/filter.html): ينشئ مجموعة فرعية من البيانات تحتوي فقط على **الصفوف** التي تلبي شروطك، وفي هذه الحالة، القرع الذي يحتوي على النص *bushel* في عمود `Package`.\n",
"\n",
"[stringr::str_detect()](https://stringr.tidyverse.org/reference/str_detect.html): يتحقق من وجود أو غياب نمط معين في النص.\n",
"\n",
"حزمة [`stringr`](https://github.com/tidyverse/stringr) توفر وظائف بسيطة لعمليات النصوص الشائعة.\n"
],
"metadata": {
"id": "L8Qfcs92ageF"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Retain only pumpkins with \"bushel\"\n",
"new_pumpkins <- pumpkins %>% \n",
" filter(str_detect(Package, \"bushel\"))\n",
"\n",
"# Get the dimensions of the new data\n",
"dim(new_pumpkins)\n",
"\n",
"# View a few rows of the new data\n",
"new_pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "hy_SGYREampd"
}
},
{
"cell_type": "markdown",
"source": [
"يمكنك أن ترى أننا قد حصرنا البيانات إلى حوالي 415 صفًا تحتوي على القرع بالجملة. 🤩 \n",
"
\n"
],
"metadata": {
"id": "VrDwF031avlR"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::case_when()\n",
"\n",
"**لكن انتظر! هناك شيء آخر يجب القيام به**\n",
"\n",
"هل لاحظت أن كمية السلة تختلف من صف لآخر؟ تحتاج إلى توحيد التسعير بحيث تعرض السعر لكل سلة، وليس لكل 1 1/9 أو 1/2 سلة. حان الوقت لإجراء بعض العمليات الحسابية لتوحيد ذلك.\n",
"\n",
"سنستخدم الدالة [`case_when()`](https://dplyr.tidyverse.org/reference/case_when.html) لتعديل عمود السعر بناءً على بعض الشروط. تتيح لك `case_when` كتابة عدة عبارات `if_else()` بشكل متجه.\n"
],
"metadata": {
"id": "mLpw2jH4a0tx"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Convert the price if the Package contains fractional bushel values\n",
"new_pumpkins <- new_pumpkins %>% \n",
" mutate(Price = case_when(\n",
" str_detect(Package, \"1 1/9\") ~ Price/(1 + 1/9),\n",
" str_detect(Package, \"1/2\") ~ Price/(1/2),\n",
" TRUE ~ Price))\n",
"\n",
"# View the first few rows of the data\n",
"new_pumpkins %>% \n",
" slice_head(n = 30)"
],
"outputs": [],
"metadata": {
"id": "P68kLVQmbM6I"
}
},
{
"cell_type": "markdown",
"source": [
"الآن يمكننا تحليل التسعير لكل وحدة بناءً على قياسها بالبوشل. كل هذا البحث حول بوشل القرع يظهر مدى `أهمية` أن `تفهم طبيعة بياناتك`!\n",
"\n",
"> ✅ وفقًا لموقع [The Spruce Eats](https://www.thespruceeats.com/how-much-is-a-bushel-1389308)، يعتمد وزن البوشل على نوع المنتج، لأنه قياس للحجم. \"على سبيل المثال، من المفترض أن يزن بوشل الطماطم 56 رطلاً... الأوراق والخضروات تشغل مساحة أكبر بوزن أقل، لذا فإن بوشل السبانخ يزن فقط 20 رطلاً.\" الأمر معقد للغاية! لن نشغل أنفسنا بتحويل البوشل إلى أرطال، وبدلاً من ذلك سنسعر بناءً على البوشل. كل هذا البحث حول بوشل القرع يظهر مدى أهمية أن تفهم طبيعة بياناتك!\n",
"\n",
"> ✅ هل لاحظت أن القرع الذي يُباع بنصف بوشل مكلف جدًا؟ هل يمكنك معرفة السبب؟ تلميح: القرع الصغير أغلى بكثير من الكبير، ربما لأن هناك عددًا أكبر منه في البوشل الواحد، نظرًا للمساحة غير المستخدمة التي يشغلها قرع الفطيرة الكبير المجوف.\n"
],
"metadata": {
"id": "pS2GNPagbSdb"
}
},
{
"cell_type": "markdown",
"source": [
"الآن أخيرًا، ومن باب المغامرة فقط 💁♀️، دعونا أيضًا ننقل عمود الشهر إلى الموضع الأول، أي \"قبل\" عمود \"Package\".\n",
"\n",
"يتم استخدام `dplyr::relocate()` لتغيير مواقع الأعمدة.\n"
],
"metadata": {
"id": "qql1SowfbdnP"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Create a new data frame new_pumpkins\n",
"new_pumpkins <- new_pumpkins %>% \n",
" relocate(Month, .before = Package)\n",
"\n",
"new_pumpkins %>% \n",
" slice_head(n = 7)"
],
"outputs": [],
"metadata": {
"id": "JJ1x6kw8bixF"
}
},
{
"cell_type": "markdown",
"source": [
"عمل رائع! 👌 لديك الآن مجموعة بيانات نظيفة ومرتبة يمكنك استخدامها لبناء نموذج الانحدار الجديد الخاص بك! \n"
],
"metadata": {
"id": "y8TJ0Za_bn5Y"
}
},
{
"cell_type": "markdown",
"source": [
"## 4. تصور البيانات باستخدام ggplot2\n",
"\n",
"
\n",
" \n",
"
\n"
],
"metadata": {
"id": "Ml7SDCLQcPvE"
}
},
{
"cell_type": "markdown",
"source": [
"### **كيف نجعلها مفيدة؟**\n",
"\n",
"لجعل الرسوم البيانية تعرض بيانات مفيدة، عادةً ما تحتاج إلى تجميع البيانات بطريقة ما. على سبيل المثال، في حالتنا، العثور على متوسط سعر القرع لكل شهر سيقدم المزيد من الأفكار حول الأنماط الأساسية في بياناتنا. هذا يقودنا إلى نظرة سريعة أخرى على **dplyr**:\n",
"\n",
"#### `dplyr::group_by() %>% summarize()`\n",
"\n",
"يمكن حساب التجميع المُجمّع في R بسهولة باستخدام\n",
"\n",
"`dplyr::group_by() %>% summarize()`\n",
"\n",
"- `dplyr::group_by()` يغير وحدة التحليل من مجموعة البيانات الكاملة إلى مجموعات فردية مثل كل شهر.\n",
"\n",
"- `dplyr::summarize()` ينشئ إطار بيانات جديد يحتوي على عمود لكل متغير تجميعي وعمود لكل إحصائية تلخيصية قمت بتحديدها.\n",
"\n",
"على سبيل المثال، يمكننا استخدام `dplyr::group_by() %>% summarize()` لتجميع القرع في مجموعات بناءً على أعمدة **الشهر** ثم العثور على **متوسط السعر** لكل شهر.\n"
],
"metadata": {
"id": "jMakvJZIcVkh"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Find the average price of pumpkins per month\r\n",
"new_pumpkins %>%\r\n",
" group_by(Month) %>% \r\n",
" summarise(mean_price = mean(Price))"
],
"outputs": [],
"metadata": {
"id": "6kVSUa2Bcilf"
}
},
{
"cell_type": "markdown",
"source": [
"موجز!✨\n",
"\n",
"الميزات التصنيفية مثل الأشهر يتم تمثيلها بشكل أفضل باستخدام مخطط الأعمدة 📊. الطبقات المسؤولة عن مخططات الأعمدة هي `geom_bar()` و `geom_col()`. راجع `?geom_bar` لمعرفة المزيد.\n",
"\n",
"لنقم بإنشاء واحد!\n"
],
"metadata": {
"id": "Kds48GUBcj3W"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Find the average price of pumpkins per month then plot a bar chart\r\n",
"new_pumpkins %>%\r\n",
" group_by(Month) %>% \r\n",
" summarise(mean_price = mean(Price)) %>% \r\n",
" ggplot(aes(x = Month, y = mean_price)) +\r\n",
" geom_col(fill = \"midnightblue\", alpha = 0.7) +\r\n",
" ylab(\"Pumpkin Price\")"
],
"outputs": [],
"metadata": {
"id": "VNbU1S3BcrxO"
}
},
{
"cell_type": "markdown",
"source": [
"🤩🤩 هذه طريقة أكثر فائدة لتصور البيانات! يبدو أنها تشير إلى أن أعلى سعر للقرع يحدث في شهري سبتمبر وأكتوبر. هل يتوافق ذلك مع توقعاتك؟ لماذا أو لماذا لا؟\n",
"\n",
"تهانينا على إنهاء الدرس الثاني 👏! لقد قمت بتحضير بياناتك لبناء النموذج، ثم اكتشفت المزيد من الأفكار باستخدام التصورات!\n"
],
"metadata": {
"id": "zDm0VOzzcuzR"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**إخلاء المسؤولية**: \nتمت ترجمة هذا المستند باستخدام خدمة الترجمة الآلية [Co-op Translator](https://github.com/Azure/co-op-translator). بينما نسعى لتحقيق الدقة، يرجى العلم أن الترجمات الآلية قد تحتوي على أخطاء أو معلومات غير دقيقة. يجب اعتبار المستند الأصلي بلغته الأصلية هو المصدر الموثوق. للحصول على معلومات حساسة أو هامة، يُوصى بالاستعانة بترجمة بشرية احترافية. نحن غير مسؤولين عن أي سوء فهم أو تفسيرات خاطئة تنشأ عن استخدام هذه الترجمة.\n"
]
}
]
}