diff --git a/en/01-dataframe.ipynb b/en/01-dataframe.ipynb index d682400..5bdc8a5 100644 --- a/en/01-dataframe.ipynb +++ b/en/01-dataframe.ipynb @@ -171,7 +171,8 @@ "source": [ "### Exercise - DataFrame and Series\n", "\n", - "1. Load the table of species from the `species.csv` file and assign the result to `species_df`." + "1. Load the table of species from the `species.csv`\n", + " file and assign the result to `species_df`. (3 min.)" ] }, { @@ -194,7 +195,7 @@ }, "source": [ "2. Use the `.unique()` function to get\n", - " the list of all different `taxa`." + " the list of all different `taxa`. (2 min.)" ] }, { @@ -209,7 +210,7 @@ }, "outputs": [], "source": [ - "species_df" + "species_df###" ] }, { @@ -220,8 +221,7 @@ }, "source": [ "3. Use the `.nunique()` function to\n", - " get the number of different taxa.\n", - " Note: `nan` will not be accounted." + " get the number of different taxa. (1 min.)" ] }, { @@ -236,7 +236,7 @@ }, "outputs": [], "source": [ - "species_df" + "species_df###" ] }, { @@ -312,7 +312,9 @@ }, "source": [ "### Exercise - Grouping\n", - "`1`. How many recorded individuals are female `F`, and how many male `M`?" + "`1`. How many recorded individuals are female `F`,\n", + "and how many male `M`? HINT: it is possible to select\n", + "a column once the data has been grouped. (2 min.)" ] }, { @@ -327,7 +329,7 @@ }, "outputs": [], "source": [ - "by_sex" + "by_sex###" ] }, { @@ -337,7 +339,8 @@ "lang": "en" }, "source": [ - "`2`. What happens when you group by two columns using the following syntax and then grab mean values:" + "`2`. What happens when you group by two columns using\n", + "the following syntax and then grab mean values? (2 min.)" ] }, { @@ -352,7 +355,7 @@ }, "outputs": [], "source": [ - "surveys_df.groupby(['plot_id', 'sex'])" + "surveys_df.groupby(['plot_id', 'sex'])###" ] }, { @@ -362,7 +365,8 @@ "lang": "en" }, "source": [ - "`3`. Summarize `weight` values for each site (`plot_id`) in your data. HINT: it is possible to select a column once the data has been grouped." + "`3`. Summarize `weight` values for each\n", + "site (`plot_id`) in your data. (3 min.)" ] }, { @@ -377,7 +381,7 @@ }, "outputs": [], "source": [ - "surveys_df" + "surveys_df###" ] }, { @@ -410,7 +414,9 @@ }, "source": [ "### Exercise - Plotting Challenge\n", - "Create a `line` plot of the median `weight` per month." + "Create a `line` plot of\n", + "[the median](https://pandas.pydata.org/docs/reference/api/pandas.Series.median.html)\n", + "`weight` per month. (3 min.)" ] }, { @@ -425,7 +431,7 @@ }, "outputs": [], "source": [ - "surveys_df" + "surveys_df###" ] }, { diff --git a/en/02-selection.ipynb b/en/02-selection.ipynb index e45fd07..6873559 100644 --- a/en/02-selection.ipynb +++ b/en/02-selection.ipynb @@ -271,7 +271,7 @@ "```\n", "Use the `isin()` method to find all different\n", "sites (`plot_id`) that contain particular species\n", - "(`AS`, `CQ`, `OX` and `UL`) in the surveys DataFrame." + "(`AS`, `CQ`, `OX` and `UL`) in the surveys DataFrame. (4 min.)" ] }, { @@ -287,10 +287,10 @@ "outputs": [], "source": [ "# Boolean mask of valid species IDs\n", - "species_mask = surveys_df['species_id']\n", + "species_mask = ###(['AS', 'CQ', 'OX', 'UL'])\n", "\n", "# List all different sites\n", - "surveys_df[species_mask]['plot_id']" + "surveys_df[###][###].unique()" ] }, { @@ -305,7 +305,9 @@ "* Create a new DataFrame that contains only observations that are\n", " of sex female or male and where weight values are greater than 0\n", "* For the final plot, only select the\n", - " weight, the site and the sex columns" + " weight, the site and the sex columns\n", + "\n", + "(5 min.)" ] }, { @@ -321,11 +323,11 @@ "outputs": [], "source": [ "# Selection of the data with isin()\n", - "sex_mask = surveys_df['sex']\n", - "weight_mask = surveys_df['weight']\n", + "sex_mask = surveys_df['sex']###\n", + "weight_mask = surveys_df['weight'] ###\n", "columns = ['weight', 'plot_id', 'sex']\n", "\n", - "selection = surveys_df\n", + "selection = surveys_df###\n", "selection.tail()" ] }, @@ -342,7 +344,7 @@ "outputs": [], "source": [ "# Calculate the mean weight for each plot_id and sex combination: \n", - "avg_by_site_sex = selection\n", + "avg_by_site_sex = selection###\n", "avg_by_site_sex.head()" ] }, diff --git a/en/03-format.ipynb b/en/03-format.ipynb index e09266b..c69dc12 100644 --- a/en/03-format.ipynb +++ b/en/03-format.ipynb @@ -377,7 +377,9 @@ "In the `sex` column of `copy_surveys_df`:\n", "* Replace undefined values by `'F|M'`\n", "* Any value not equal to `'F'`, `'M'` or `'F|M'` is\n", - " considered invalid and must be replaced by `'F|M'`" + " considered invalid and must be replaced by `'F|M'`\n", + "\n", + "(5 min.)" ] }, { diff --git a/en/04-combine.ipynb b/en/04-combine.ipynb index 4b4ca99..6bb9a95 100644 --- a/en/04-combine.ipynb +++ b/en/04-combine.ipynb @@ -161,9 +161,8 @@ "* In `surveys_df`, select rows where the year is 2001.\n", " Do the same for year 2002.\n", "* Concatenate both dataframes.\n", - "* Compute the average weight by sex for each year.\n", - "* Export your results as a CSV and make\n", - " sure it reads back into python properly." + "\n", + "(3 min.)" ] }, { @@ -186,6 +185,16 @@ "survey_all = ###" ] }, + { + "cell_type": "markdown", + "id": "4eacaca5-19e9-48c4-bbe7-74e28323d13a", + "metadata": { + "lang": "en" + }, + "source": [ + "* Compute the average weight by sex for each year. (1 min.)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -204,6 +213,17 @@ "weight_year" ] }, + { + "cell_type": "markdown", + "id": "96877605-e612-45fb-8203-438b2b72a9c1", + "metadata": { + "lang": "en" + }, + "source": [ + "* Export your results as a CSV and make sure\n", + " it reads back into python properly. (2 min.)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -399,7 +419,8 @@ "source": [ "## Exercise - Joining all data\n", "`1`. Create a new DataFrame by joining the contents of the\n", - "`surveys.csv` and `species.csv` tables. Keep all survey records." + "`surveys.csv` and `species.csv` tables. Keep all survey records.\n", + "(3 min.)" ] }, { @@ -429,8 +450,8 @@ "lang": "en" }, "source": [ - "`2`. Calculate and plot the distribution of surveys\n", - "(i.e. the number of `record_id`) by `taxa` for each `plot_id`." + "`2`. Calculate and plot the distribution of surveys (i.e. the\n", + "number of `record_id`) by `taxa` for each `plot_id`. (3 min.)" ] }, { @@ -470,7 +491,7 @@ }, "source": [ "`3`. Calculate and plot the distribution\n", - "of `taxa` by `sex` for each `plot_id`." + "of `taxa` by `sex` for each `plot_id`. (2 min.)" ] }, { diff --git a/en/05-altair.ipynb b/en/05-altair.ipynb index ecdfca5..92a0bd4 100644 --- a/en/05-altair.ipynb +++ b/en/05-altair.ipynb @@ -297,7 +297,9 @@ "* For the X axis, specify the `'plot_id'` field and the\n", " [`'ordinal'` type](https://altair-viz.github.io/user_guide/encodings/#encoding-data-types)\n", "* For the Y axis, specify `'count()'` as a temporary field computed\n", - " automatically by Altair, which saves us from using `groupby()`" + " automatically by Altair, which saves us from using `groupby()`\n", + "\n", + "(4 min.)" ] }, { @@ -490,7 +492,9 @@ " and `'M'` to colors `'orange'` and `'green'`, respectively.\n", " See [an example here](https://altair-viz.github.io/user_guide/customization.html#color-domain-and-range)\n", "* Activate the `tooltip` channel with\n", - " `'count()'` in order to get the count by sex" + " `'count()'` in order to get the count by sex\n", + "\n", + "(4 min.)" ] }, { @@ -579,7 +583,7 @@ "source": [ "### Exercise - Plotting time series data\n", "`1`. Use the `pd.to_datetime()` function to generate a new\n", - "`date` column from the columns `year`, `month` and `day`." + "`date` column from the columns `year`, `month` and `day`. (3 min.)" ] }, { @@ -609,7 +613,8 @@ "lang": "en" }, "source": [ - "`2`. Visualize the median weight of each species by the `date`." + "`2`. Visualize the median weight of each species by the `date`.\n", + "(3 min.)" ] }, { @@ -755,7 +760,9 @@ "* Each facet will have:\n", " * Years on the X axis\n", " * The average weight on the Y axis\n", - " * One colored line per species" + " * One colored line per species\n", + "\n", + "(5 min.)" ] }, { @@ -856,7 +863,7 @@ "full species names on the X axis of a boxplot.\n", "\n", "`1`. Compute the left-join of `surveys_complete`\n", - "and all the species details in `species.csv`." + "and all the species details in `species.csv`. (3 min.)" ] }, { @@ -892,7 +899,9 @@ "* The noisy weights on the Y axis, with a logarithmic\n", " scale in base 2 and with the label \"Weight (g)\"\n", "* One color for each species identifier\n", - "* A title for the graphic" + "* A title for the graphic\n", + "\n", + "(6 min.)" ] }, { diff --git a/fr/01-dataframe.ipynb b/fr/01-dataframe.ipynb index 26f399d..68362db 100644 --- a/fr/01-dataframe.ipynb +++ b/fr/01-dataframe.ipynb @@ -173,7 +173,7 @@ "### Exercice - DataFrame et Series\n", "\n", "1. Chargez la table des espèces animales du fichier\n", - " `species.csv` et assignez le résultat à `especes_df`." + " `species.csv` et assignez le résultat à `especes_df`. (3 min.)" ] }, { @@ -195,8 +195,8 @@ "lang": "fr" }, "source": [ - "2. Utilisez la méthode `.unique()` pour obtenir\n", - " la liste des différents taxons (colonne `taxa`)." + "2. Utilisez la méthode `.unique()` pour obtenir la\n", + " liste des différents taxons (colonne `taxa`). (2 min.)" ] }, { @@ -211,7 +211,7 @@ }, "outputs": [], "source": [ - "especes_df" + "especes_df###" ] }, { @@ -222,8 +222,7 @@ }, "source": [ "3. Utilisez la méthode `.nunique()` pour obtenir\n", - " le nombre de différents taxons.\n", - " Note : `nan` ne sera pas compté." + " le nombre de différents taxons. (1 min.)" ] }, { @@ -238,7 +237,7 @@ }, "outputs": [], "source": [ - "especes_df" + "especes_df###" ] }, { @@ -316,7 +315,7 @@ "### Exercice - Grouper des données\n", "`1`. Combien de femelles `F` et combien de mâles `M`?\n", "Indice : c'est possible de sélectionner une\n", - "seule colonne après avoir groupé les données." + "seule colonne après avoir groupé les données. (2 min.)" ] }, { @@ -331,7 +330,7 @@ }, "outputs": [], "source": [ - "par_sex" + "par_sex###" ] }, { @@ -341,7 +340,8 @@ "lang": "fr" }, "source": [ - "`2`. Qu'arrive-t-il si on groupe par deux colonnes et si on recalcule les moyennes?" + "`2`. Qu'arrive-t-il si on groupe par deux colonnes\n", + "et si on recalcule les moyennes? (2 min.)" ] }, { @@ -356,7 +356,7 @@ }, "outputs": [], "source": [ - "surveys_df.groupby(['plot_id', 'sex'])" + "surveys_df.groupby(['plot_id', 'sex'])###" ] }, { @@ -367,7 +367,7 @@ }, "source": [ "`3`. Faites calculer un sommaire des statistiques descriptives\n", - "des poids (`weight`) pour chaque site (`plot_id`)." + "des poids (`weight`) pour chaque site (`plot_id`). (3 min.)" ] }, { @@ -382,7 +382,7 @@ }, "outputs": [], "source": [ - "surveys_df" + "surveys_df###" ] }, { @@ -415,7 +415,9 @@ }, "source": [ "### Exercice - Créer un graphique\n", - "Créez un graphique de type `line` montrant la médiane des poids`weight` pour chaque mois." + "Créez un graphique de type `line` montrant\n", + "[la médiane](https://pandas.pydata.org/docs/reference/api/pandas.Series.median.html)\n", + "des poids `weight` pour chaque mois. (3 min.)" ] }, { @@ -430,7 +432,7 @@ }, "outputs": [], "source": [ - "surveys_df" + "surveys_df###" ] }, { diff --git a/fr/02-selection.ipynb b/fr/02-selection.ipynb index 6f92177..d3bb76d 100644 --- a/fr/02-selection.ipynb +++ b/fr/02-selection.ipynb @@ -8,14 +8,14 @@ }, "source": [ "# Analyse et visualisation de données avec Python\n", - "## Sélectionner des rangées et des colonnes\n", + "## Sélectionner des lignes et des colonnes de données\n", "Questions\n", "* Comment accéder à des données spécifiques dans un dataframe?\n", "\n", "Objectives\n", "* Utiliser les tranches pour sélectionner un intervalle de données.\n", - "* Utiliser les étiquettes de rangées et les noms\n", - " de colonnes pour délimiter une tranche.\n", + "* Utiliser les étiquettes de lignes de données et\n", + " les noms de colonnes pour délimiter une tranche.\n", "* Réassigner des valeurs à une sélection dans un dataframe.\n", "* Effectuer une sélection en utilisant un critère contenant\n", " un opérateur : `=`, `!=`, `>`, `<`, `>=`, `<=`.\n", @@ -109,10 +109,10 @@ "lang": "fr" }, "source": [ - "### Faire une sélection selon des rangées et des colonnes\n", - "On peut sélectionner un sous-ensemble de\n", - "rangées et de colonnes avec l'attribut `loc` :\n", - "c'est principalement basé sur les index de rangée et de colonne." + "### Faire une sélection selon des lignes et des colonnes de données\n", + "On peut sélectionner un sous-ensemble de lignes\n", + "et de colonnes de données avec l'attribut `loc` :\n", + "c'est basé sur les index de ligne et de colonne." ] }, { @@ -137,7 +137,7 @@ }, "outputs": [], "source": [ - "# Sélectionner toutes les colonnes pour les rangées 0 et 10\n", + "# Sélectionner toutes les colonnes pour les lignes 0 et 10\n", "surveys_df.loc[[0, 10], :]" ] }, @@ -272,7 +272,7 @@ "```\n", "Utilisez la méthode `isin()` pour trouver tous les\n", "différents sites (`plot_id`) ayant certaines espèces\n", - "(`AS`, `CQ`, `OX` et `UL`) dans le DataFrame." + "(`AS`, `CQ`, `OX` et `UL`) dans le DataFrame. (4 min.)" ] }, { @@ -288,10 +288,10 @@ "outputs": [], "source": [ "# Masque booléen selon le code de l'espèce\n", - "cond_especes = surveys_df['species_id']\n", + "cond_especes = ###(['AS', 'CQ', 'OX', 'UL'])\n", "\n", "# Lister les différents sites\n", - "surveys_df[cond_especes]['plot_id']" + "surveys_df[###][###].unique()" ] }, { @@ -308,7 +308,9 @@ "* Créez une sélection contenant seulement les enregistrements\n", "ayant une valeur de `sex` (soit `F` ou `M`) et ayant un poids supérieur à 0\n", "* Pour le graphique final, vous devez limiter les données\n", - "aux colonnes de poids, de site et de sexe" + "aux colonnes de poids, de site et de sexe\n", + "\n", + "(5 min.)" ] }, { @@ -324,11 +326,11 @@ "outputs": [], "source": [ "# Sélection des enregistrements et des colonnes nécessaires\n", - "cond_sexe = surveys_df['sex']\n", - "cond_poids = surveys_df['weight']\n", + "cond_sexe = surveys_df['sex']###\n", + "cond_poids = surveys_df['weight'] ###\n", "colonnes = ['weight', 'plot_id', 'sex']\n", "\n", - "selection = surveys_df\n", + "selection = surveys_df###\n", "selection.tail()" ] }, @@ -345,7 +347,7 @@ "outputs": [], "source": [ "# Grouper selon les sites et les sexes, calculer les moyennes\n", - "moy_par_site_sexe = selection\n", + "moy_par_site_sexe = selection###\n", "moy_par_site_sexe.tail()" ] }, @@ -422,10 +424,11 @@ " * Avec une liste : sélection de colonnes\n", " * Avec un vecteur de valeurs booléennes : sélection de lignes\n", " * `df.loc[lignes, colonnes]` :\n", - " * Avec une liste : pour des rangées ou colonnes\n", - " * Intervalle avec `:` : pour des rangées ou colonnes\n", + " * Avec une liste : pour des lignes ou colonnes de données\n", + " * Intervalle avec `:` : pour des lignes ou colonnes de données\n", " * Les deux limites sont incluses\n", - " * Avec un vecteur de valeurs booléennes : sélection de rangées\n", + " * Avec un vecteur de valeurs booléennes :\n", + " sélection de lignes de données\n", " * Permet l'assignation d'une valeur selon la sélection\n", " * `colonne.isin([valeur1, valeur2, ...])`\n", "* **Opérateurs** sur les valeurs d'une ou de deux colonnes :\n", diff --git a/fr/03-format.ipynb b/fr/03-format.ipynb index 7999bba..d5226ba 100644 --- a/fr/03-format.ipynb +++ b/fr/03-format.ipynb @@ -377,7 +377,9 @@ "Dans la colonne `sex` de `copie_surveys` :\n", "* Remplacez les valeurs non-définies par `'F|M'`\n", "* Tout ce qui n'est pas `'F'`, `'M'` ou `'F|M'` est considéré\n", - " invalide et on veut remplacer ces valeurs par `'F|M'`" + " invalide et on veut remplacer ces valeurs par `'F|M'`\n", + "\n", + "(5 min.)" ] }, { diff --git a/fr/04-combine.ipynb b/fr/04-combine.ipynb index 5988f58..cf9586c 100644 --- a/fr/04-combine.ipynb +++ b/fr/04-combine.ipynb @@ -160,8 +160,8 @@ "## Exercice - Concaténer des DataFrames\n", "* Dans `surveys_df`, sélectionnez individuellement les enregistrements des années 2001 et 2002\n", "* Concaténez les deux dataframes verticalement\n", - "* Calculez le poids moyen selon l'année et le sexe\n", - "* Sauvegardez le tableau des moyennes dans un fichier CSV et le recharger" + "\n", + "(3 min.)" ] }, { @@ -184,6 +184,16 @@ "deux_annees = ###" ] }, + { + "cell_type": "markdown", + "id": "706b172d-43e4-4fbe-957d-dc3fda02d15f", + "metadata": { + "lang": "fr" + }, + "source": [ + "* Calculez le poids moyen selon l'année et le sexe (1 min.)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -202,6 +212,17 @@ "poids_annee" ] }, + { + "cell_type": "markdown", + "id": "7bcb08cd-40d9-45c1-bcca-8bdfe1e20b01", + "metadata": { + "lang": "fr" + }, + "source": [ + "* Sauvegardez le tableau des moyennes\n", + " dans un fichier CSV et le recharger (2 min.)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -384,8 +405,8 @@ }, "source": [ "### Les autres types de jonction\n", - "* `how='right'` : toutes les rangées du second DataFrame sont gardées\n", - "* `how='outer'` : équivalent d'une union, toutes les rangées sont gardées" + "* `how='right'` : toutes les lignes du second DataFrame sont gardées\n", + "* `how='outer'` : équivalent d'une union, toutes les lignes sont gardées" ] }, { @@ -398,7 +419,8 @@ "## Exercice - Joindre toutes les données\n", "`1`. Créez un nouveau DataFrame tel que tous les\n", "enregistrements de `surveys.csv` sont gardés dans une jonction\n", - "impliquant les informations correspondantes de `species.csv`." + "impliquant les informations correspondantes de `species.csv`.\n", + "(3 min.)" ] }, { @@ -430,7 +452,7 @@ "source": [ "`2`. Calculez et créez un graphique (*bar-plot*) montrant\n", "le nombre d'enregistrements (soit le nombre de `record_id`)\n", - "par type de `taxa` pour chaque site (`plot_id`)." + "par type de `taxa` pour chaque site (`plot_id`). (3 min.)" ] }, { @@ -470,7 +492,8 @@ }, "source": [ "`3`. Calculez et créez un graphique (bar-plot) montrant le nombre\n", - "de différents `taxa` par type de sexe pour chaque site (`plot_id`)." + "de différents `taxa` par type de sexe pour chaque site (`plot_id`).\n", + "(2 min.)" ] }, { diff --git a/fr/05-altair.ipynb b/fr/05-altair.ipynb index 60c3a79..0ea4bef 100644 --- a/fr/05-altair.ipynb +++ b/fr/05-altair.ipynb @@ -90,7 +90,7 @@ "Étant donné que les graphiques générés par Altair ne sont pas que des\n", "images statiques, l'information générée est parfois très lourde et\n", "elle s'accumule dans le notebook s'il y a plusieurs graphiques.\n", - "Néanmoins, pour contourner la limite de 5000 rangées dans le DataFrame\n", + "Néanmoins, pour contourner la limite de 5000 lignes dans le DataFrame\n", "de données, on peut désactiver cette limite, à nos risques." ] }, @@ -297,7 +297,9 @@ " [type `'ordinal'`](https://altair-viz.github.io/user_guide/encodings/#encoding-data-types)\n", "* Sur l'axe vertical, spécifiez `'count()'` comme variable pour que\n", " Altair fasse automatiquement le décompte, ce qui évite de passer\n", - " par la méthode `groupby()` du DataFrame" + " par la méthode `groupby()` du DataFrame\n", + "\n", + "(4 min.)" ] }, { @@ -488,7 +490,9 @@ " de domaine `'F'` et `'M'` aux couleurs `'orange'` et `'green'`.\n", " Voir [un exemple ici](https://altair-viz.github.io/user_guide/customization.html#color-domain-and-range)\n", "* Activez le canal `tooltip` avec `'count()'` pour avoir le décompte\n", - " par sexe" + " par sexe\n", + "\n", + "(4 min.)" ] }, { @@ -577,7 +581,7 @@ "source": [ "### Exercice - Visualisation selon le temps\n", "`1`. Utilisez la fonction `pd.to_datetime()` pour générer une colonne\n", - " de dates à partir des colonnes `year`, `month` et `day`." + " de dates à partir des colonnes `year`, `month` et `day`. (3 min.)" ] }, { @@ -607,7 +611,8 @@ "lang": "fr" }, "source": [ - "`2`. Affichez le poids médian de chaque espèce selon la `date`." + "`2`. Affichez le poids médian de chaque espèce selon la `date`.\n", + "(3 min.)" ] }, { @@ -752,7 +757,9 @@ "* Chaque facette aura :\n", " * Les années en axe des x\n", " * Le poids moyen en axe des y\n", - " * Une courbe de couleur par espèce" + " * Une courbe de couleur par espèce\n", + "\n", + "(5 min.)" ] }, { @@ -854,7 +861,7 @@ "l'axe horizontal d'un box-plot.\n", "\n", "`1`. Recalculez la jonction de gauche entre `surveys_complet` et\n", - " le détail des espèces dans `species.csv`." + " le détail des espèces dans `species.csv`. (3 min.)" ] }, { @@ -890,7 +897,9 @@ "* Le poids bruité dans l'axe vertical, selon une échelle logarithmique\n", " en base 2 et avec l'étiquette \"Poids (g)\"\n", "* Une couleur selon l'identifiant d'espèce\n", - "* Un titre pour le graphique" + "* Un titre pour le graphique\n", + "\n", + "(6 min.)" ] }, { diff --git a/solution-en/01-dataframe.ipynb b/solution-en/01-dataframe.ipynb index 2407951..afb5486 100644 --- a/solution-en/01-dataframe.ipynb +++ b/solution-en/01-dataframe.ipynb @@ -171,7 +171,8 @@ "source": [ "### Exercise - DataFrame and Series\n", "\n", - "1. Load the table of species from the `species.csv` file and assign the result to `species_df`." + "1. Load the table of species from the `species.csv`\n", + " file and assign the result to `species_df`. (3 min.)" ] }, { @@ -197,7 +198,7 @@ }, "source": [ "2. Use the `.unique()` function to get\n", - " the list of all different `taxa`." + " the list of all different `taxa`. (2 min.)" ] }, { @@ -223,8 +224,7 @@ }, "source": [ "3. Use the `.nunique()` function to\n", - " get the number of different taxa.\n", - " Note: `nan` will not be accounted." + " get the number of different taxa. (1 min.)" ] }, { @@ -315,7 +315,9 @@ }, "source": [ "### Exercise - Grouping\n", - "`1`. How many recorded individuals are female `F`, and how many male `M`?" + "`1`. How many recorded individuals are female `F`,\n", + "and how many male `M`? HINT: it is possible to select\n", + "a column once the data has been grouped. (2 min.)" ] }, { @@ -340,7 +342,8 @@ "lang": "en" }, "source": [ - "`2`. What happens when you group by two columns using the following syntax and then grab mean values:" + "`2`. What happens when you group by two columns using\n", + "the following syntax and then grab mean values? (2 min.)" ] }, { @@ -365,7 +368,8 @@ "lang": "en" }, "source": [ - "`3`. Summarize `weight` values for each site (`plot_id`) in your data. HINT: it is possible to select a column once the data has been grouped." + "`3`. Summarize `weight` values for each\n", + "site (`plot_id`) in your data. (3 min.)" ] }, { @@ -413,7 +417,9 @@ }, "source": [ "### Exercise - Plotting Challenge\n", - "Create a `line` plot of the median `weight` per month." + "Create a `line` plot of\n", + "[the median](https://pandas.pydata.org/docs/reference/api/pandas.Series.median.html)\n", + "`weight` per month. (3 min.)" ] }, { diff --git a/solution-en/02-selection.ipynb b/solution-en/02-selection.ipynb index 78ec097..8ed7e58 100644 --- a/solution-en/02-selection.ipynb +++ b/solution-en/02-selection.ipynb @@ -271,7 +271,7 @@ "```\n", "Use the `isin()` method to find all different\n", "sites (`plot_id`) that contain particular species\n", - "(`AS`, `CQ`, `OX` and `UL`) in the surveys DataFrame." + "(`AS`, `CQ`, `OX` and `UL`) in the surveys DataFrame. (4 min.)" ] }, { @@ -305,7 +305,9 @@ "* Create a new DataFrame that contains only observations that are\n", " of sex female or male and where weight values are greater than 0\n", "* For the final plot, only select the\n", - " weight, the site and the sex columns" + " weight, the site and the sex columns\n", + "\n", + "(5 min.)" ] }, { diff --git a/solution-en/03-format.ipynb b/solution-en/03-format.ipynb index e8664dd..b6ac15c 100644 --- a/solution-en/03-format.ipynb +++ b/solution-en/03-format.ipynb @@ -377,7 +377,9 @@ "In the `sex` column of `copy_surveys_df`:\n", "* Replace undefined values by `'F|M'`\n", "* Any value not equal to `'F'`, `'M'` or `'F|M'` is\n", - " considered invalid and must be replaced by `'F|M'`" + " considered invalid and must be replaced by `'F|M'`\n", + "\n", + "(5 min.)" ] }, { diff --git a/solution-en/04-combine.ipynb b/solution-en/04-combine.ipynb index 4660c54..029d6e7 100644 --- a/solution-en/04-combine.ipynb +++ b/solution-en/04-combine.ipynb @@ -161,9 +161,8 @@ "* In `surveys_df`, select rows where the year is 2001.\n", " Do the same for year 2002.\n", "* Concatenate both dataframes.\n", - "* Compute the average weight by sex for each year.\n", - "* Export your results as a CSV and make\n", - " sure it reads back into python properly." + "\n", + "(3 min.)" ] }, { @@ -186,6 +185,16 @@ "survey_all = pd.concat([survey2001, survey2002], axis='index')" ] }, + { + "cell_type": "markdown", + "id": "4eacaca5-19e9-48c4-bbe7-74e28323d13a", + "metadata": { + "lang": "en" + }, + "source": [ + "* Compute the average weight by sex for each year. (1 min.)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -204,6 +213,17 @@ "weight_year" ] }, + { + "cell_type": "markdown", + "id": "96877605-e612-45fb-8203-438b2b72a9c1", + "metadata": { + "lang": "en" + }, + "source": [ + "* Export your results as a CSV and make sure\n", + " it reads back into python properly. (2 min.)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -399,7 +419,8 @@ "source": [ "## Exercise - Joining all data\n", "`1`. Create a new DataFrame by joining the contents of the\n", - "`surveys.csv` and `species.csv` tables. Keep all survey records." + "`surveys.csv` and `species.csv` tables. Keep all survey records.\n", + "(3 min.)" ] }, { @@ -429,8 +450,8 @@ "lang": "en" }, "source": [ - "`2`. Calculate and plot the distribution of surveys\n", - "(i.e. the number of `record_id`) by `taxa` for each `plot_id`." + "`2`. Calculate and plot the distribution of surveys (i.e. the\n", + "number of `record_id`) by `taxa` for each `plot_id`. (3 min.)" ] }, { @@ -470,7 +491,7 @@ }, "source": [ "`3`. Calculate and plot the distribution\n", - "of `taxa` by `sex` for each `plot_id`." + "of `taxa` by `sex` for each `plot_id`. (2 min.)" ] }, { diff --git a/solution-en/05-altair.ipynb b/solution-en/05-altair.ipynb index 88b0978..d127673 100644 --- a/solution-en/05-altair.ipynb +++ b/solution-en/05-altair.ipynb @@ -297,7 +297,9 @@ "* For the X axis, specify the `'plot_id'` field and the\n", " [`'ordinal'` type](https://altair-viz.github.io/user_guide/encodings/#encoding-data-types)\n", "* For the Y axis, specify `'count()'` as a temporary field computed\n", - " automatically by Altair, which saves us from using `groupby()`" + " automatically by Altair, which saves us from using `groupby()`\n", + "\n", + "(4 min.)" ] }, { @@ -490,7 +492,9 @@ " and `'M'` to colors `'orange'` and `'green'`, respectively.\n", " See [an example here](https://altair-viz.github.io/user_guide/customization.html#color-domain-and-range)\n", "* Activate the `tooltip` channel with\n", - " `'count()'` in order to get the count by sex" + " `'count()'` in order to get the count by sex\n", + "\n", + "(4 min.)" ] }, { @@ -579,7 +583,7 @@ "source": [ "### Exercise - Plotting time series data\n", "`1`. Use the `pd.to_datetime()` function to generate a new\n", - "`date` column from the columns `year`, `month` and `day`." + "`date` column from the columns `year`, `month` and `day`. (3 min.)" ] }, { @@ -609,7 +613,8 @@ "lang": "en" }, "source": [ - "`2`. Visualize the median weight of each species by the `date`." + "`2`. Visualize the median weight of each species by the `date`.\n", + "(3 min.)" ] }, { @@ -755,7 +760,9 @@ "* Each facet will have:\n", " * Years on the X axis\n", " * The average weight on the Y axis\n", - " * One colored line per species" + " * One colored line per species\n", + "\n", + "(5 min.)" ] }, { @@ -856,7 +863,7 @@ "full species names on the X axis of a boxplot.\n", "\n", "`1`. Compute the left-join of `surveys_complete`\n", - "and all the species details in `species.csv`." + "and all the species details in `species.csv`. (3 min.)" ] }, { @@ -892,7 +899,9 @@ "* The noisy weights on the Y axis, with a logarithmic\n", " scale in base 2 and with the label \"Weight (g)\"\n", "* One color for each species identifier\n", - "* A title for the graphic" + "* A title for the graphic\n", + "\n", + "(6 min.)" ] }, { diff --git a/solution-fr/01-dataframe.ipynb b/solution-fr/01-dataframe.ipynb index e708ddb..ad6082a 100644 --- a/solution-fr/01-dataframe.ipynb +++ b/solution-fr/01-dataframe.ipynb @@ -173,7 +173,7 @@ "### Exercice - DataFrame et Series\n", "\n", "1. Chargez la table des espèces animales du fichier\n", - " `species.csv` et assignez le résultat à `especes_df`." + " `species.csv` et assignez le résultat à `especes_df`. (3 min.)" ] }, { @@ -198,8 +198,8 @@ "lang": "fr" }, "source": [ - "2. Utilisez la méthode `.unique()` pour obtenir\n", - " la liste des différents taxons (colonne `taxa`)." + "2. Utilisez la méthode `.unique()` pour obtenir la\n", + " liste des différents taxons (colonne `taxa`). (2 min.)" ] }, { @@ -225,8 +225,7 @@ }, "source": [ "3. Utilisez la méthode `.nunique()` pour obtenir\n", - " le nombre de différents taxons.\n", - " Note : `nan` ne sera pas compté." + " le nombre de différents taxons. (1 min.)" ] }, { @@ -319,7 +318,7 @@ "### Exercice - Grouper des données\n", "`1`. Combien de femelles `F` et combien de mâles `M`?\n", "Indice : c'est possible de sélectionner une\n", - "seule colonne après avoir groupé les données." + "seule colonne après avoir groupé les données. (2 min.)" ] }, { @@ -344,7 +343,8 @@ "lang": "fr" }, "source": [ - "`2`. Qu'arrive-t-il si on groupe par deux colonnes et si on recalcule les moyennes?" + "`2`. Qu'arrive-t-il si on groupe par deux colonnes\n", + "et si on recalcule les moyennes? (2 min.)" ] }, { @@ -370,7 +370,7 @@ }, "source": [ "`3`. Faites calculer un sommaire des statistiques descriptives\n", - "des poids (`weight`) pour chaque site (`plot_id`)." + "des poids (`weight`) pour chaque site (`plot_id`). (3 min.)" ] }, { @@ -418,7 +418,9 @@ }, "source": [ "### Exercice - Créer un graphique\n", - "Créez un graphique de type `line` montrant la médiane des poids`weight` pour chaque mois." + "Créez un graphique de type `line` montrant\n", + "[la médiane](https://pandas.pydata.org/docs/reference/api/pandas.Series.median.html)\n", + "des poids `weight` pour chaque mois. (3 min.)" ] }, { diff --git a/solution-fr/02-selection.ipynb b/solution-fr/02-selection.ipynb index 6c63938..56df111 100644 --- a/solution-fr/02-selection.ipynb +++ b/solution-fr/02-selection.ipynb @@ -8,14 +8,14 @@ }, "source": [ "# Analyse et visualisation de données avec Python\n", - "## Sélectionner des rangées et des colonnes\n", + "## Sélectionner des lignes et des colonnes de données\n", "Questions\n", "* Comment accéder à des données spécifiques dans un dataframe?\n", "\n", "Objectives\n", "* Utiliser les tranches pour sélectionner un intervalle de données.\n", - "* Utiliser les étiquettes de rangées et les noms\n", - " de colonnes pour délimiter une tranche.\n", + "* Utiliser les étiquettes de lignes de données et\n", + " les noms de colonnes pour délimiter une tranche.\n", "* Réassigner des valeurs à une sélection dans un dataframe.\n", "* Effectuer une sélection en utilisant un critère contenant\n", " un opérateur : `=`, `!=`, `>`, `<`, `>=`, `<=`.\n", @@ -109,10 +109,10 @@ "lang": "fr" }, "source": [ - "### Faire une sélection selon des rangées et des colonnes\n", - "On peut sélectionner un sous-ensemble de\n", - "rangées et de colonnes avec l'attribut `loc` :\n", - "c'est principalement basé sur les index de rangée et de colonne." + "### Faire une sélection selon des lignes et des colonnes de données\n", + "On peut sélectionner un sous-ensemble de lignes\n", + "et de colonnes de données avec l'attribut `loc` :\n", + "c'est basé sur les index de ligne et de colonne." ] }, { @@ -137,7 +137,7 @@ }, "outputs": [], "source": [ - "# Sélectionner toutes les colonnes pour les rangées 0 et 10\n", + "# Sélectionner toutes les colonnes pour les lignes 0 et 10\n", "surveys_df.loc[[0, 10], :]" ] }, @@ -272,7 +272,7 @@ "```\n", "Utilisez la méthode `isin()` pour trouver tous les\n", "différents sites (`plot_id`) ayant certaines espèces\n", - "(`AS`, `CQ`, `OX` et `UL`) dans le DataFrame." + "(`AS`, `CQ`, `OX` et `UL`) dans le DataFrame. (4 min.)" ] }, { @@ -308,7 +308,9 @@ "* Créez une sélection contenant seulement les enregistrements\n", "ayant une valeur de `sex` (soit `F` ou `M`) et ayant un poids supérieur à 0\n", "* Pour le graphique final, vous devez limiter les données\n", - "aux colonnes de poids, de site et de sexe" + "aux colonnes de poids, de site et de sexe\n", + "\n", + "(5 min.)" ] }, { @@ -422,10 +424,11 @@ " * Avec une liste : sélection de colonnes\n", " * Avec un vecteur de valeurs booléennes : sélection de lignes\n", " * `df.loc[lignes, colonnes]` :\n", - " * Avec une liste : pour des rangées ou colonnes\n", - " * Intervalle avec `:` : pour des rangées ou colonnes\n", + " * Avec une liste : pour des lignes ou colonnes de données\n", + " * Intervalle avec `:` : pour des lignes ou colonnes de données\n", " * Les deux limites sont incluses\n", - " * Avec un vecteur de valeurs booléennes : sélection de rangées\n", + " * Avec un vecteur de valeurs booléennes :\n", + " sélection de lignes de données\n", " * Permet l'assignation d'une valeur selon la sélection\n", " * `colonne.isin([valeur1, valeur2, ...])`\n", "* **Opérateurs** sur les valeurs d'une ou de deux colonnes :\n", diff --git a/solution-fr/03-format.ipynb b/solution-fr/03-format.ipynb index 0c3a69b..41dc3a1 100644 --- a/solution-fr/03-format.ipynb +++ b/solution-fr/03-format.ipynb @@ -377,7 +377,9 @@ "Dans la colonne `sex` de `copie_surveys` :\n", "* Remplacez les valeurs non-définies par `'F|M'`\n", "* Tout ce qui n'est pas `'F'`, `'M'` ou `'F|M'` est considéré\n", - " invalide et on veut remplacer ces valeurs par `'F|M'`" + " invalide et on veut remplacer ces valeurs par `'F|M'`\n", + "\n", + "(5 min.)" ] }, { diff --git a/solution-fr/04-combine.ipynb b/solution-fr/04-combine.ipynb index da60b7f..a108af5 100644 --- a/solution-fr/04-combine.ipynb +++ b/solution-fr/04-combine.ipynb @@ -160,8 +160,8 @@ "## Exercice - Concaténer des DataFrames\n", "* Dans `surveys_df`, sélectionnez individuellement les enregistrements des années 2001 et 2002\n", "* Concaténez les deux dataframes verticalement\n", - "* Calculez le poids moyen selon l'année et le sexe\n", - "* Sauvegardez le tableau des moyennes dans un fichier CSV et le recharger" + "\n", + "(3 min.)" ] }, { @@ -184,6 +184,16 @@ "deux_annees = pd.concat([annee2001, annee2002], axis='index')" ] }, + { + "cell_type": "markdown", + "id": "706b172d-43e4-4fbe-957d-dc3fda02d15f", + "metadata": { + "lang": "fr" + }, + "source": [ + "* Calculez le poids moyen selon l'année et le sexe (1 min.)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -202,6 +212,17 @@ "poids_annee" ] }, + { + "cell_type": "markdown", + "id": "7bcb08cd-40d9-45c1-bcca-8bdfe1e20b01", + "metadata": { + "lang": "fr" + }, + "source": [ + "* Sauvegardez le tableau des moyennes\n", + " dans un fichier CSV et le recharger (2 min.)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -384,8 +405,8 @@ }, "source": [ "### Les autres types de jonction\n", - "* `how='right'` : toutes les rangées du second DataFrame sont gardées\n", - "* `how='outer'` : équivalent d'une union, toutes les rangées sont gardées" + "* `how='right'` : toutes les lignes du second DataFrame sont gardées\n", + "* `how='outer'` : équivalent d'une union, toutes les lignes sont gardées" ] }, { @@ -398,7 +419,8 @@ "## Exercice - Joindre toutes les données\n", "`1`. Créez un nouveau DataFrame tel que tous les\n", "enregistrements de `surveys.csv` sont gardés dans une jonction\n", - "impliquant les informations correspondantes de `species.csv`." + "impliquant les informations correspondantes de `species.csv`.\n", + "(3 min.)" ] }, { @@ -430,7 +452,7 @@ "source": [ "`2`. Calculez et créez un graphique (*bar-plot*) montrant\n", "le nombre d'enregistrements (soit le nombre de `record_id`)\n", - "par type de `taxa` pour chaque site (`plot_id`)." + "par type de `taxa` pour chaque site (`plot_id`). (3 min.)" ] }, { @@ -470,7 +492,8 @@ }, "source": [ "`3`. Calculez et créez un graphique (bar-plot) montrant le nombre\n", - "de différents `taxa` par type de sexe pour chaque site (`plot_id`)." + "de différents `taxa` par type de sexe pour chaque site (`plot_id`).\n", + "(2 min.)" ] }, { diff --git a/solution-fr/05-altair.ipynb b/solution-fr/05-altair.ipynb index 1f5f105..05aa802 100644 --- a/solution-fr/05-altair.ipynb +++ b/solution-fr/05-altair.ipynb @@ -90,7 +90,7 @@ "Étant donné que les graphiques générés par Altair ne sont pas que des\n", "images statiques, l'information générée est parfois très lourde et\n", "elle s'accumule dans le notebook s'il y a plusieurs graphiques.\n", - "Néanmoins, pour contourner la limite de 5000 rangées dans le DataFrame\n", + "Néanmoins, pour contourner la limite de 5000 lignes dans le DataFrame\n", "de données, on peut désactiver cette limite, à nos risques." ] }, @@ -297,7 +297,9 @@ " [type `'ordinal'`](https://altair-viz.github.io/user_guide/encodings/#encoding-data-types)\n", "* Sur l'axe vertical, spécifiez `'count()'` comme variable pour que\n", " Altair fasse automatiquement le décompte, ce qui évite de passer\n", - " par la méthode `groupby()` du DataFrame" + " par la méthode `groupby()` du DataFrame\n", + "\n", + "(4 min.)" ] }, { @@ -488,7 +490,9 @@ " de domaine `'F'` et `'M'` aux couleurs `'orange'` et `'green'`.\n", " Voir [un exemple ici](https://altair-viz.github.io/user_guide/customization.html#color-domain-and-range)\n", "* Activez le canal `tooltip` avec `'count()'` pour avoir le décompte\n", - " par sexe" + " par sexe\n", + "\n", + "(4 min.)" ] }, { @@ -577,7 +581,7 @@ "source": [ "### Exercice - Visualisation selon le temps\n", "`1`. Utilisez la fonction `pd.to_datetime()` pour générer une colonne\n", - " de dates à partir des colonnes `year`, `month` et `day`." + " de dates à partir des colonnes `year`, `month` et `day`. (3 min.)" ] }, { @@ -607,7 +611,8 @@ "lang": "fr" }, "source": [ - "`2`. Affichez le poids médian de chaque espèce selon la `date`." + "`2`. Affichez le poids médian de chaque espèce selon la `date`.\n", + "(3 min.)" ] }, { @@ -752,7 +757,9 @@ "* Chaque facette aura :\n", " * Les années en axe des x\n", " * Le poids moyen en axe des y\n", - " * Une courbe de couleur par espèce" + " * Une courbe de couleur par espèce\n", + "\n", + "(5 min.)" ] }, { @@ -854,7 +861,7 @@ "l'axe horizontal d'un box-plot.\n", "\n", "`1`. Recalculez la jonction de gauche entre `surveys_complet` et\n", - " le détail des espèces dans `species.csv`." + " le détail des espèces dans `species.csv`. (3 min.)" ] }, { @@ -890,7 +897,9 @@ "* Le poids bruité dans l'axe vertical, selon une échelle logarithmique\n", " en base 2 et avec l'étiquette \"Poids (g)\"\n", "* Une couleur selon l'identifiant d'espèce\n", - "* Un titre pour le graphique" + "* Un titre pour le graphique\n", + "\n", + "(6 min.)" ] }, {