Skip to content

Commit

Permalink
Relecture de la partie numpy/pandas (#152)
Browse files Browse the repository at this point in the history
* suite des relectures Kim (#151)

* coquilles suite à séance 1 de TP

* relecture numpy

* 02b_pandas_TP

* Update content/course/getting-started/06_rappels_fonctions.Rmd

* Update content/course/getting-started/06_rappels_fonctions.Rmd

* Update content/course/getting-started/06_rappels_fonctions.Rmd

Co-authored-by: Lino Galiana <33896139+linogaliana@users.noreply.github.com>

* Automated changes

* build light version

* Automated changes

* modifs de forme

* Automated changes

* pandas tutorial badge

* Automated changes

Co-authored-by: Kim A <kim.antunez@ensae.fr>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 27, 2021
1 parent 90af6f4 commit 2fa78c9
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 50 deletions.
2 changes: 1 addition & 1 deletion build/build_light.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
content_rmd <- list.files("./content/course", recursive = TRUE, pattern = "*.Rmd", full.names = TRUE)
content_rmd <- content_rmd[!grepl("/git/", content_rmd)]
content_rmd <- content_rmd[!grepl("06a_exo_supp_webscraping.", content_rmd)]
content_rmd <- content_rmd[1:3]
content_rmd <- content_rmd[5:6]

file.remove(
gsub(
Expand Down
7 changes: 6 additions & 1 deletion content/course/getting-started/05_rappels_types.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -305,12 +305,17 @@ liste_nombres.index(7)
```{python, include = FALSE, eval = FALSE}
# Correction
# 4 clefs
print(len(dict1.keys()))
print(len(dictionnaire_evangile.keys()))
```

- Que faut-il écrire pour obtenir "Ange" en résultat à partir du dictionnaire_evangile ?


```{python, include = FALSE, eval = FALSE}
dictionnaire_evangile["Matthieu"][0]
```


## Objets : méthodes et attributs

Maintenant qu'on a vu quels objets existent en Python, nous allons
Expand Down
21 changes: 11 additions & 10 deletions content/course/getting-started/06_rappels_fonctions.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,6 @@ data.head()
### from _Module_ Import _fonction_ - seulement une partie du module


{{< panel status="warning" title="Warning" icon="fa fa-exclamation-triangle" >}}
Cette méthode n'est pas recommandée car elle rend le code moins intelligible:
d'où vient la fonction `floor`: de `maths` ou de `numpy` ? Elle risque
aussi de créer des conflits de fonction, qui malgré un nom commun peuvent ne
pas attendre les mêmes arguments ou objets
**LIEN VERS PARTIE BONNE PRATIQUE**
{{< /panel >}}




Expand All @@ -120,7 +112,16 @@ Si on ne veut pas être obligé de donner le nom du module avant d'appeler
la fonction, il y a toujours la possibilité de n'importer qu'une fonction du module. Dans le cas de l'exemple, Python sait que la fonction `arrange` est celle de `numpy`.

Mais ___attention___ : si deux fonctions de modules différents ont le même nom, c'est toujours la dernière importée qui gagne.
On voit souvent from _module_ import \*. C'est-à-dire qu'on importe toutes les fonctions du module mais on n'a pas besoin de spécifier le nom du module avant les méthodes. Faire cela peut être dangereux si vous faites ça pour tous vos modules.

On voit souvent `from _module_ import *`. C'est-à-dire qu'on importe toutes les fonctions du module mais on n'a pas besoin de spécifier le nom du module avant les méthodes.

{{% panel status="warning" title="Warning" icon="fa fa-exclamation-triangle" %}}
La méthode from _module_ import \* n'est pas recommandée car elle rend le code moins intelligible:
d'où vient la fonction `floor`: de `maths` ou de `numpy` ? Elle risque
aussi de créer des conflits de fonction, qui malgré un nom commun peuvent ne
pas attendre les mêmes arguments ou objets.
{{% /panel %}}


```{python}
from numpy import array
Expand Down Expand Up @@ -528,7 +529,7 @@ def inverse(x) :
```{python, include = FALSE, eval = FALSE}
# Correction
print(inverse(1))
# On voit que le return est mal placé ! Dans le cas de x différent de 0 on ne revoit rien !
# On voit que le return est mal placé ! Dans le cas de x différent de 0 on ne renvoie rien !
```

- Ecrivez un programme qui peut trouver tous les nombres divisibles par 7 et non multiples de 5 entre 6523 et 8463 (inclus)
Expand Down
55 changes: 39 additions & 16 deletions content/course/manipulation/01_numpy.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ il suffit d'utiliser la méthode `array`:

```{python}
np.array([1,2,5])
np.array([["a","z","e"],["r","t"],["y"]])
np.array([["a","z","e"],["r","t"],["y"]], dtype="object")
```

Il existe aussi des méthodes pratiques pour créer des array:
Expand All @@ -126,14 +126,17 @@ np.full((3, 5), 3.14)
np.eye(3)
```

**Exercice :**

{{% panel status="exercise" title="Exercise 1" icon="fas fa-pencil-alt" %}}

Générer:

* $X$ une variable aléatoire, 1000 répétitions d'une loi $U(0,1)$
* $Y$ une variable aléatoire, 1000 répétitions d'une loi normale de moyenne nulle et de variance égale à 2
* Vérifier la variance de $Y$ avec `np.var`

{{% /panel %}}


```{python, include = FALSE, eval = FALSE}
# Correction
Expand Down Expand Up @@ -186,15 +189,17 @@ x[2]
```

Les syntaxes qui permettent de sélectionner des indices particuliers d'une liste fonctionnent également
avec les arrays:
avec les arrays.

**Exercice**
{{% panel status="exercise" title="Exercise 2" icon="fas fa-pencil-alt" %}}

* Sélectionner les éléments 0,3,5
* Sélectionner les éléments pairs
* Sélectionner tous les éléments sauf le premier
* Sélectionner les 5 premiers éléments

{{% /panel %}}


```{python, include = FALSE, eval = FALSE}
# Correction
Expand All @@ -209,8 +214,7 @@ x[:5]

Un élément déterminant dans la performance de `numpy` par rapport aux listes, lorsqu'il est question de
*slicing* est qu'un array ne renvoie pas une
copie de l'élément en question (copie qui coûte de la mémoire et du temps) mais simplement une vue de celui-ci
**DETAILS**
copie de l'élément en question (copie qui coûte de la mémoire et du temps) mais simplement une vue de celui-ci.

Lorsqu'il est nécessaire d'effectuer une copie, par exemple pour ne pas altérer l'array sous-jacent, on peut
utiliser la méthode `copy`:
Expand Down Expand Up @@ -249,7 +253,7 @@ x2<0
Pour sélectionner les observations relatives à la condition logique,
il suffit d'utiliser la logique de *slicing* de `numpy` qui fonctionne avec les conditions logiques

**Exercice**
{{% panel status="exercise" title="Exercise 3" icon="fas fa-pencil-alt" %}}

Soit

Expand All @@ -262,6 +266,7 @@ x = np.random.normal(size=10000)
3. Sommer les valeurs absolues de toutes les observations supérieures (en valeur absolue) à 1.96
et rapportez les à la somme des valeurs de `x` (en valeur absolue)

{{% /panel %}}


```{python, eval = FALSE, include = FALSE}
Expand All @@ -283,7 +288,7 @@ qui gèrent bien la dimension). Parmi elles, on peut retrouver:
* `any` ; `all` ; notamment avec l'argument `axis`
* `np.array_equal` pour vérifier, élément par élément, l'égalité

**Exercice**
{{% panel status="exercise" title="Exercise 4" icon="fas fa-pencil-alt" %}}

Soit

Expand All @@ -301,7 +306,13 @@ un *array* unidimensionnel présentant une valeur manquante.

1. Utiliser `count_nonzero` sur `y`
2. Utiliser `isnan` sur `y` et compter le nombre de valeurs non NaN
2. Vérifier que `x` comporte au moins une valeur positive dans son ensemble, dans chaque array et en
3. Vérifier que `x` comporte au moins une valeur positive dans son ensemble, en parcourant les lignes puis les colonnes.

Note : Jetez un oeil à ce que correspond le paramètre `axis` dans `numpy` en vous documentant sur internet. Par exemple [ici](https://www.sharpsightlabs.com/blog/numpy-axes-explained/).

{{% /panel %}}



```{python, include = FALSE, eval = FALSE}
# Correction
Expand All @@ -310,10 +321,16 @@ y = np.array([np.nan, 0, 1])
print(x)
print(y)
# 1. Utiliser `count_nonzero` sur `y`
print(np.count_nonzero(y))
# 2. Utiliser `isnan` sur `y` et compter le nombre de valeurs non NaN
print(np.isnan(y))
print(np.sum(np.isnan(y)))
# 3. Vérifier que `x` comporte au moins une valeur positive dans son ensemble, en parcourant les lignes puis les colonnes
print(np.any(x>0))
print(np.any(x>0, axis = 0))
print(np.any(x>0, axis = 1))
```

## Manipuler un array
Expand All @@ -329,13 +346,16 @@ x = np.random.normal(0, size=(3, 4))
Pour les statistiques descriptives classiques, `numpy` propose un certain nombre de fonctions déjà implémentées,
qui peuvent être combinées avec l'argument `axis`

**Exercice**
{{% panel status="exercise" title="Exercise 5" icon="fas fa-pencil-alt" %}}

1. Faire la somme de tous les éléments d'un `array`, des éléments en ligne et des éléments en colonne. Vérifier
la cohérence
2. Ecrire une fonction `statdesc` pour renvoyer les valeurs suivantes : moyenne, médiane, écart-type, minimum et maximum.
L'appliquer sur `x` en jouant avec l'argument axis

{{% /panel %}}


```{python, include = FALSE, eval = FALSE}
# Correction
x.sum()
Expand Down Expand Up @@ -428,7 +448,7 @@ a + 5

Le *broadcasting* peut être très pratique pour effectuer de manière efficace des opérations sur des données à
la structure complexe. Pour plus de détails, se rendre
[ici](https://jakevdp.github.io/PythonDataScienceHandbook/02.05-computation-on-arrays-broadcasting.html).
[ici](https://jakevdp.github.io/PythonDataScienceHandbook/02.05-computation-on-arrays-broadcasting.html) ou [ici](https://stackoverflow.com/questions/47435526/what-is-the-meaning-of-axis-1-in-keras-argmax).

## Application: k-nearest neighbor fait-main

Expand Down Expand Up @@ -502,20 +522,23 @@ X = np.random.rand(10, 2)
# 2. Nuage de points.
import matplotlib.pyplot as plt
#plt.scatter(X[:, 0], X[:, 1], s=100)
print(X[:,0])
print(X[:,1])
plt.scatter(X[:, 0], X[:, 1], s=100)
# 3. Construire la matrice des distances euclidiennes
print(X.shape)
X1 = X[:, np.newaxis, :]
print(X1.shape)
print("dimension X1 : ", X1.shape)
X2 = X[np.newaxis, :,:]
print(X2.shape)
print("dimension X2 : ", X2.shape)
dist1 = (X1 - X2) ** 2
print(dist1.shape)
print("dimension dist1 : ", dist1.shape)
dist = np.sqrt(np.sum((X1 - X2) ** 2, axis=-1))
print(dist.shape)
print("dimension dist : ", dist.shape)
# 4. Vérif termes diagonaux
print(dist)
print(dist.diagonal())
#5. Classer avec np.argsort
Expand Down
46 changes: 24 additions & 22 deletions content/course/manipulation/02a_pandas_tutorial.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,10 @@ np.random.seed(123)

Au cours de cette démonstration des principales fonctionalités de `pandas`, et
lors du TP
[![Onyxia](https://img.shields.io/badge/SSPcloud-Tester%20via%20SSP--cloud-informational&color=yellow?logo=Python)](https://datalab.sspcloud.fr/launcher/inseefrlab-helm-charts-datascience/jupyter?onyxia.friendlyName=%C2%ABpython-datascientist%C2%BB&resources.requests.memory=%C2%AB4Gi%C2%BB)
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/linogaliana/python-datascientist/master?filepath=content/manipulation/notebooks/02_pandas_tp.ipynb)
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](http://colab.research.google.com/github/linogaliana/python-datascientist/blob/master/content/manipulation/notebooks/02_pandas_tp.ipynb)

```{r, echo = FALSE, results = 'asis', include = TRUE, eval = TRUE}
print_badges("content/course/manipulation/02b_pandas_TP.Rmd")
```


Je recommande de se référer régulièrement aux ressources suivantes:
Expand Down Expand Up @@ -245,10 +246,10 @@ taille['koala']

L'existence d'indice rend le *subsetting* particulièrement aisé, ce que vous
pouvez expérimenter dans les TP
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/linogaliana/python-datascientist/master)
[![Onyxia](https://img.shields.io/badge/SSPcloud-Tester%20via%20SSP--cloud-informational&color=yellow?logo=Python)](https://datalab.sspcloud.fr/launcher/inseefrlab-helm-charts-datascience/jupyter?onyxia.friendlyName=%C2%ABpython-datascientist%C2%BB&resources.requests.memory=%C2%AB4Gi%C2%BB)
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](http://colab.research.google.com/github/linogaliana/python-datascientist/blob/pandas_intro/static/notebooks/numpy.ipynb)
([ou depuis github](https://github.com/linogaliana/python-datascientist/blob/master/content/01_data/02_pandas_tp.ipynb))

```{r, echo = FALSE, results = 'asis', include = TRUE, eval = TRUE}
print_badges("content/course/manipulation/02b_pandas_TP.Rmd")
```



Expand Down Expand Up @@ -386,10 +387,11 @@ Pour présenter les méthodes les plus pratiques pour l'analyse de données,
on peut partir de l'exemple des consommations de CO2 communales issues
des données de l'Ademe. Cette base de données est exploitée plus intensément
dans le TP
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/linogaliana/python-datascientist/master)
[![Onyxia](https://img.shields.io/badge/SSPcloud-Tester%20via%20SSP--cloud-informational&color=yellow?logo=Python)](https://datalab.sspcloud.fr/launcher/inseefrlab-helm-charts-datascience/jupyter?onyxia.friendlyName=%C2%ABpython-datascientist%C2%BB&resources.requests.memory=%C2%AB4Gi%C2%BB)
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](http://colab.research.google.com/github/linogaliana/python-datascientist/blob/pandas_intro/static/notebooks/numpy.ipynb)
([ou depuis github](https://github.com/linogaliana/python-datascientist/blob/master/content/01_data/02_pandas_tp.ipynb))

```{r, echo = FALSE, results = 'asis', include = TRUE, eval = TRUE}
print_badges("content/course/manipulation/02b_pandas_TP.Rmd")
```


```{python}
df = pd.read_csv("https://koumoul.com/s/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/convert")
Expand All @@ -414,11 +416,10 @@ nom l'indique, de n'afficher que les premières lignes ;
nom l'indique, de n'afficher que les dernières lignes
* `sample` qui permet d'afficher un échantillon aléatoire de *n* lignes.
Cette méthode propose de nombreuses options
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/linogaliana/python-datascientist/master)
[![Onyxia](https://img.shields.io/badge/SSPcloud-Tester%20via%20SSP--cloud-informational&color=yellow?logo=Python)](https://datalab.sspcloud.fr/launcher/inseefrlab-helm-charts-datascience/jupyter?onyxia.friendlyName=%C2%ABpython-datascientist%C2%BB&resources.requests.memory=%C2%AB4Gi%C2%BB)
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](http://colab.research.google.com/github/linogaliana/python-datascientist/blob/pandas_intro/static/notebooks/numpy.ipynb)
([ou depuis github](https://github.com/linogaliana/python-datascientist/blob/master/content/01_data/02_pandas_tp.ipynb))

```{r, echo = FALSE, results = 'asis', include = TRUE, eval = TRUE}
print_badges("content/course/manipulation/02b_pandas_TP.Rmd")
```

[^2]: Il est préférable d'utiliser la fonction `display` (ou tout simplement
taper le nom du DataFrame qu'utiliser la fonction `print`). Le
Expand Down Expand Up @@ -507,10 +508,11 @@ df.quantile(q = [0.1,0.25,0.5,0.75,0.9])
Il faut toujours regarder les options de ces fonctions en termes de valeurs manquantes, car
ces options sont déterminantes dans le résultat obtenu.

Les exercices de TD ([![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/linogaliana/python-datascientist/master)
[![Onyxia](https://img.shields.io/badge/SSPcloud-Tester%20via%20SSP--cloud-informational&color=yellow?logo=Python)](https://datalab.sspcloud.fr/launcher/inseefrlab-helm-charts-datascience/jupyter?onyxia.friendlyName=%C2%ABpython-datascientist%C2%BB&resources.requests.memory=%C2%AB4Gi%C2%BB)
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](http://colab.research.google.com/github/linogaliana/python-datascientist/blob/pandas_intro/static/notebooks/numpy.ipynb) [ou depuis github](https://github.com/linogaliana/python-datascientist/blob/master/content/01_data/02_pandas_tp.ipynb))
visent à démontrer l'intérêt de ces méthodes dans quelques cas précis.
Les exercices de TD visent à démontrer l'intérêt de ces méthodes dans quelques cas précis.

```{r, echo = FALSE, results = 'asis', include = TRUE, eval = TRUE}
print_badges("content/course/manipulation/02b_pandas_TP.Rmd")
```

<!---
Comme indiqué précédemment, il faut faire attention aux valeurs manquantes qui,
Expand Down Expand Up @@ -594,7 +596,7 @@ fig
plt.savefig('plot_hist_log.png', bbox_inches='tight')
```

```{r}
```{r, echo = FALSE}
knitr::include_graphics("plot_base.png")
knitr::include_graphics("plot_hist.png")
knitr::include_graphics("plot_hist_log.png")
Expand Down Expand Up @@ -984,8 +986,8 @@ Se référer à la documentation de `concat` pour voir les options possibles.

On présente généralement deux types de données:

* format __wide__: les données comportent des observations répétées, pour un même individu (ou groupe), dans des colonnes différentes
* format __long__: les données comportent des observations répétées, pour un même individu, dans des lignes différentes avec une colonne permettant de distinguer les niveaux d'observations
* format __wide__: les données comportent des observations répétées, pour un même individu (ou groupe), dans des colonnes différentes
* format __long__: les données comportent des observations répétées, pour un même individu, dans des lignes différentes avec une colonne permettant de distinguer les niveaux d'observations

Un exemple de la distinction entre les deux peut être pris à l'ouvrage de référence d'Hadley Wickham, *R for Data Science*:

Expand Down
9 changes: 9 additions & 0 deletions content/course/manipulation/02b_pandas_TP.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -507,3 +507,12 @@ df_merged.corr()['empreinte'].nlargest(10)
On peut utiliser `apply` pour passer des fonctions à appliquer sur plusieurs colonnes ou sur plusieurs valeurs
----->

# Exercices bonus

Les plus rapides d'entre vous sont invités à aller un peu plus loin en s'entraînant avec des exercices bonus qui proviennent du [site de Xavier Dupré](http://www.xavierdupre.fr/app/ensae_teaching_cs/helpsphinx3). 3 notebooks en lien avec `numpy` et `pandas` vous y sont proposés :

1. Calcul Matriciel, Optimisation : [énoncé](http://www.xavierdupre.fr/app/ensae_teaching_cs/helpsphinx3/notebooks/td2a_cenonce_session_2A.html) / [corrigé](http://www.xavierdupre.fr/app/ensae_teaching_cs/helpsphinx3/notebooks/td2a_correction_session_2A.html)
2. DataFrame et Graphes : [énoncé](http://www.xavierdupre.fr/app/ensae_teaching_cs/helpsphinx3/notebooks/td2a_cenonce_session_1.html) / [corrigé](http://www.xavierdupre.fr/app/ensae_teaching_cs/helpsphinx3/notebooks/td2a_correction_session_1.html)
3. Pandas et itérateurs : [énoncé](http://www.xavierdupre.fr/app/ensae_teaching_cs/helpsphinx3/notebooks/pandas_iterator.html) / [corrigé](http://www.xavierdupre.fr/app/ensae_teaching_cs/helpsphinx3/notebooks/pandas_iterator_correction.html)

0 comments on commit 2fa78c9

Please sign in to comment.