{ "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-09-04T01:38:13+00:00", "source_file": "2-Regression/2-Data/solution/R/lesson_2-R.ipynb", "language_code": "fr" } }, "cells": [ { "cell_type": "markdown", "source": [ "# Construire un modèle de régression : préparer et visualiser les données\n", "\n", "## **Régression linéaire pour les citrouilles - Leçon 2**\n", "#### Introduction\n", "\n", "Maintenant que vous disposez des outils nécessaires pour commencer à construire des modèles de machine learning avec Tidymodels et le Tidyverse, vous êtes prêt à poser des questions à vos données. Lorsque vous travaillez avec des données et appliquez des solutions de machine learning, il est crucial de savoir poser les bonnes questions pour exploiter pleinement le potentiel de votre jeu de données.\n", "\n", "Dans cette leçon, vous apprendrez :\n", "\n", "- Comment préparer vos données pour la construction de modèles.\n", "\n", "- Comment utiliser `ggplot2` pour la visualisation des données.\n", "\n", "La question à laquelle vous souhaitez répondre déterminera le type d'algorithmes de machine learning que vous utiliserez. Et la qualité de la réponse que vous obtiendrez dépendra fortement de la nature de vos données.\n", "\n", "Voyons cela à travers un exercice pratique.\n", "\n", "
\n",
" \n",
"
\n",
"\n",
"> Un rappel : L'opérateur pipe (`%>%`) permet d'effectuer des opérations dans une séquence logique en passant un objet à une fonction ou une expression d'appel. Vous pouvez considérer l'opérateur pipe comme signifiant \"et ensuite\" dans votre code.\n"
],
"metadata": {
"id": "REWcIv9yX29v"
}
},
{
"cell_type": "markdown",
"source": [
"## 2. Vérifier les données manquantes\n",
"\n",
"L'un des problèmes les plus courants auxquels les data scientists doivent faire face est celui des données incomplètes ou manquantes. R représente les valeurs manquantes ou inconnues avec une valeur sentinelle spéciale : `NA` (Non Disponible).\n",
"\n",
"Alors, comment savoir si le tableau de données contient des valeurs manquantes ?\n",
"
\n",
"- Une méthode simple serait d'utiliser la fonction de base R `anyNA`, qui retourne les objets logiques `TRUE` ou `FALSE`.\n"
],
"metadata": {
"id": "Zxfb3AM5YbUe"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"pumpkins %>% \n",
" anyNA()"
],
"outputs": [],
"metadata": {
"id": "G--DQutAYltj"
}
},
{
"cell_type": "markdown",
"source": [
"Super, il semble qu'il manque certaines données ! C'est un bon point de départ.\n",
"\n",
"- Une autre méthode consisterait à utiliser la fonction `is.na()` qui indique quels éléments individuels d'une colonne sont manquants avec une valeur logique `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": [
"D'accord, c'est fait, mais avec un grand tableau de données comme celui-ci, il serait inefficace et pratiquement impossible de vérifier toutes les lignes et colonnes individuellement 😴.\n",
"\n",
"- Une méthode plus intuitive serait de calculer la somme des valeurs manquantes pour chaque colonne :\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": [
"Bien mieux ! Il manque des données, mais peut-être que cela n'aura pas d'importance pour la tâche en cours. Voyons ce que l'analyse supplémentaire peut révéler.\n",
"\n",
"> En plus des ensembles impressionnants de packages et de fonctions, R dispose d'une très bonne documentation. Par exemple, utilisez `help(colSums)` ou `?colSums` pour en savoir plus sur la fonction.\n"
],
"metadata": {
"id": "9gv-crB6ZD1Y"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. Dplyr : Une grammaire pour manipuler les données\n",
"\n",
"
\n",
" \n",
"
\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": [
"Ouiii !💪\n",
"\n",
"\"Mais attendez !\", direz-vous après avoir parcouru rapidement l'ensemble des données avec `View(pumpkins)`, \"Il y a quelque chose d'étrange ici !\"🤔\n",
"\n",
"Si vous regardez la colonne `Package`, les citrouilles sont vendues dans de nombreuses configurations différentes. Certaines sont vendues en mesures de `1 1/9 boisseau`, d'autres en mesures de `1/2 boisseau`, certaines à l'unité, d'autres au poids, et certaines dans de grandes caisses de largeurs variables.\n",
"\n",
"Vérifions cela :\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": [
"Incroyable !👏\n",
"\n",
"Les citrouilles semblent être très difficiles à peser de manière cohérente, alors filtrons-les en sélectionnant uniquement les citrouilles contenant le mot *bushel* dans la colonne `Package` et mettons cela dans un nouveau cadre de données `new_pumpkins`.\n"
],
"metadata": {
"id": "7sMjiVujaZxY"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::filter() et stringr::str_detect()\n",
"\n",
"[`dplyr::filter()`](https://dplyr.tidyverse.org/reference/filter.html) : crée un sous-ensemble des données ne contenant que les **lignes** qui remplissent vos conditions, dans ce cas, les citrouilles ayant le mot *bushel* dans la colonne `Package`.\n",
"\n",
"[stringr::str_detect()](https://stringr.tidyverse.org/reference/str_detect.html) : détecte la présence ou l'absence d'un motif dans une chaîne de caractères.\n",
"\n",
"Le package [`stringr`](https://github.com/tidyverse/stringr) fournit des fonctions simples pour les opérations courantes sur les chaînes de caractères.\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": [
"Vous pouvez voir que nous avons réduit à environ 415 lignes de données contenant des citrouilles par boisseau.🤩\n",
"
\n"
],
"metadata": {
"id": "VrDwF031avlR"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::case_when()\n",
"\n",
"**Mais attendez ! Il y a encore une chose à faire**\n",
"\n",
"Avez-vous remarqué que la quantité par boisseau varie selon les lignes ? Vous devez normaliser les prix afin d'afficher le prix par boisseau, et non par 1 1/9 ou 1/2 boisseau. Il est temps de faire quelques calculs pour standardiser cela.\n",
"\n",
"Nous allons utiliser la fonction [`case_when()`](https://dplyr.tidyverse.org/reference/case_when.html) pour *modifier* la colonne Price en fonction de certaines conditions. `case_when` permet de vectoriser plusieurs instructions `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": [
"Nous pouvons maintenant analyser le prix par unité en fonction de leur mesure en boisseaux. Toute cette étude des boisseaux de citrouilles, cependant, montre à quel point il est `important` de `comprendre la nature de vos données` !\n",
"\n",
"> ✅ Selon [The Spruce Eats](https://www.thespruceeats.com/how-much-is-a-bushel-1389308), le poids d'un boisseau dépend du type de produit, car il s'agit d'une mesure de volume. \"Un boisseau de tomates, par exemple, est censé peser 56 livres... Les feuilles et les légumes verts occupent plus d'espace avec moins de poids, donc un boisseau d'épinards ne pèse que 20 livres.\" Tout cela est assez compliqué ! Ne nous embêtons pas à convertir les boisseaux en livres, et fixons plutôt les prix par boisseau. Toute cette étude des boisseaux de citrouilles, cependant, montre à quel point il est important de comprendre la nature de vos données !\n",
">\n",
"> ✅ Avez-vous remarqué que les citrouilles vendues au demi-boisseau sont très chères ? Pouvez-vous deviner pourquoi ? Indice : les petites citrouilles coûtent beaucoup plus cher que les grosses, probablement parce qu'il y en a beaucoup plus par boisseau, étant donné l'espace inutilisé occupé par une grosse citrouille creuse pour tarte.\n"
],
"metadata": {
"id": "pS2GNPagbSdb"
}
},
{
"cell_type": "markdown",
"source": [
"Maintenant, pour le simple plaisir de l'aventure 💁♀️, déplaçons également la colonne Mois à la première position, c'est-à-dire avant la colonne `Package`.\n",
"\n",
"`dplyr::relocate()` est utilisé pour modifier la position des colonnes.\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": [
"Bon travail !👌 Vous avez maintenant un ensemble de données propre et bien organisé sur lequel vous pouvez construire votre nouveau modèle de régression !\n"
],
"metadata": {
"id": "y8TJ0Za_bn5Y"
}
},
{
"cell_type": "markdown",
"source": [
"## 4. Visualisation des données avec ggplot2\n",
"\n",
"
\n",
" \n",
"