{ "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-29T23:12:22+00:00", "source_file": "2-Regression/2-Data/solution/R/lesson_2-R.ipynb", "language_code": "bn" } }, "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",
"> একটি পুনঃস্মরণ: পাইপ অপারেটর (`%>%`) লজিক্যাল ক্রমে অপারেশন সম্পাদন করে একটি অবজেক্টকে একটি ফাংশন বা কল এক্সপ্রেশনে এগিয়ে পাঠিয়ে। আপনি পাইপ অপারেটরকে আপনার কোডে \"এবং তারপর\" বলার মতো ভাবতে পারেন।\n"
],
"metadata": {
"id": "REWcIv9yX29v"
}
},
{
"cell_type": "markdown",
"source": [
"## ২. অনুপস্থিত ডেটা পরীক্ষা করুন\n",
"\n",
"ডেটা বিজ্ঞানীদের জন্য সবচেয়ে সাধারণ সমস্যাগুলোর একটি হলো অসম্পূর্ণ বা অনুপস্থিত ডেটা নিয়ে কাজ করা। R-এ অনুপস্থিত বা অজানা মানগুলোকে একটি বিশেষ সংকেত মান দিয়ে প্রকাশ করা হয়: `NA` (Not Available)।\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",
"চলুন, `Date` কলাম ব্যবহার করে `mutate`-এর কার্যকারিতা পরীক্ষা করি এবং নিচের কাজগুলো সম্পন্ন করি:\n",
"\n",
"1. তারিখগুলো (যা বর্তমানে character টাইপে আছে) মাসের ফরম্যাটে রূপান্তর করি (এগুলো US তারিখ, তাই ফরম্যাট হলো `MM/DD/YYYY`)।\n",
"\n",
"2. তারিখ থেকে মাস বের করে একটি নতুন কলামে সংরক্ষণ করি।\n",
"\n",
"R-এ, [lubridate](https://lubridate.tidyverse.org/) প্যাকেজটি Date-time ডেটা নিয়ে কাজ করা সহজ করে তোলে। সুতরাং, চলুন `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",
"কুমড়াগুলোকে ধারাবাহিকভাবে ওজন করা বেশ কঠিন বলে মনে হচ্ছে, তাই চলুন আমরা সেগুলো ফিল্টার করি যেগুলোর `Package` কলামে *bushel* স্ট্রিং রয়েছে এবং এগুলোকে একটি নতুন ডেটা ফ্রেম `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): ডেটার একটি উপসেট তৈরি করে যা শুধুমাত্র সেই **সারি** গুলো রাখে যা আপনার শর্ত পূরণ করে, এই ক্ষেত্রে, `Package` কলামে *bushel* স্ট্রিং থাকা কুমড়াগুলো।\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": [
"আপনি দেখতে পাচ্ছেন যে আমরা প্রায় ৪১৫টি সারি ডেটা সীমিত করেছি, যেখানে কুমড়া বাসেল হিসেবে রয়েছে।🤩 \n",
"
\n"
],
"metadata": {
"id": "VrDwF031avlR"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::case_when()\n",
"\n",
"**কিন্তু অপেক্ষা করুন! আরও একটি কাজ বাকি আছে**\n",
"\n",
"আপনি কি লক্ষ্য করেছেন যে প্রতি সারিতে বাসেলের পরিমাণ ভিন্ন? আপনাকে মূল্য নির্ধারণকে স্বাভাবিক করতে হবে যাতে আপনি প্রতি বাসেলের মূল্য দেখান, ১ ১/৯ বা ১/২ বাসেলের নয়। এটি মানক করার জন্য কিছু গণিত করার সময়।\n",
"\n",
"আমরা [`case_when()`](https://dplyr.tidyverse.org/reference/case_when.html) ফাংশন ব্যবহার করব *Price* কলামটি পরিবর্তন করতে কিছু শর্তের উপর ভিত্তি করে। `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) অনুযায়ী, বাসেলের ওজন উৎপাদনের ধরণের উপর নির্ভর করে, কারণ এটি একটি আয়তনের পরিমাপ। \"উদাহরণস্বরূপ, টমেটোর একটি বাসেল ৫৬ পাউন্ড ওজনের হওয়া উচিত... পাতা এবং শাকসবজি বেশি জায়গা নেয় কিন্তু কম ওজনের হয়, তাই পালং শাকের একটি বাসেল মাত্র ২০ পাউন্ড।\" এটি বেশ জটিল! চলুন বাসেল থেকে পাউন্ডে রূপান্তর করার ঝামেলা না করি এবং বাসেল অনুযায়ী মূল্য নির্ধারণ করি। তবে, কুমড়ার বাসেল নিয়ে এই সমস্ত অধ্যয়ন দেখায় যে আপনার ডেটার প্রকৃতি বুঝতে কতটা গুরুত্বপূর্ণ!\n",
">\n",
"> ✅ আপনি কি লক্ষ্য করেছেন যে অর্ধ-বাসেল কুমড়া বিক্রি খুবই ব্যয়বহুল? আপনি কি এর কারণ বের করতে পারেন? ইঙ্গিত: ছোট কুমড়াগুলো বড়গুলোর তুলনায় অনেক বেশি দামী, সম্ভবত কারণ একটি বড় ফাঁপা পাই কুমড়া যে জায়গা নেয়, তার তুলনায় ছোট কুমড়াগুলো বাসেলে অনেক বেশি থাকে।\n"
],
"metadata": {
"id": "pS2GNPagbSdb"
}
},
{
"cell_type": "markdown",
"source": [
"এখন শেষ পর্যন্ত, শুধুমাত্র মজার জন্য 💁♀️, চলুন `Month` কলামটি প্রথম অবস্থানে সরিয়ে নিই অর্থাৎ `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",
"