Skip to content

Commit 7006f60

Browse files
authored
Une première PR qui gère plein de bugs détectés par Nicolas (#630)
* lien manipulation pandas close #617 * numpy random number generation * numbers * multidiemnsional * close #623 * close #624 * close #630
1 parent 623ad9e commit 7006f60

File tree

15 files changed

+145
-120
lines changed

15 files changed

+145
-120
lines changed

_quarto.yml

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,8 @@ project:
33
render:
44
- index.qmd
55
- 404.qmd
6-
- content/getting-started/index.qmd
7-
- content/getting-started/01_environment.qmd
8-
- content/getting-started/02_data_analysis.qmd
9-
- content/getting-started/03_revisions.qmd
106
- content/manipulation/index.qmd
117
- content/manipulation/01_numpy.qmd
12-
- content/manipulation/02_pandas_intro.qmd
13-
- content/manipulation/02_pandas_suite.qmd
14-
- content/manipulation/02a_pandas_tutorial.qmd
15-
- content/manipulation/02b_pandas_TP.qmd
16-
- content/manipulation/03_geopandas_intro.qmd
17-
- content/manipulation/03_geopandas_tutorial.qmd
18-
- content/manipulation/03_geopandas_TP.qmd
19-
- content/manipulation/04a_webscraping_TP.qmd
20-
- content/manipulation/04c_API_TP.qmd
21-
- content/manipulation/04b_regex_TP.qmd
22-
- content/manipulation/05_parquet_s3.qmd
23-
- content/visualisation/index.qmd
24-
- content/visualisation/matplotlib.qmd
25-
- content/visualisation/maps.qmd
26-
- content/modelisation/index.qmd
27-
- content/modelisation/0_preprocessing.qmd
28-
- content/modelisation/1_modelevaluation.qmd
29-
- content/modelisation/2_classification.qmd
30-
- content/modelisation/3_regression.qmd
31-
- content/modelisation/4_featureselection.qmd
32-
- content/modelisation/5_clustering.qmd
33-
- content/modelisation/6_pipeline.qmd
34-
- content/modelisation/7_mlapi.qmd
35-
- content/NLP/index.qmd
36-
- content/NLP/01_intro.qmd
37-
- content/NLP/02_exoclean.qmd
38-
- content/NLP/03_embedding.qmd
39-
- content/modern-ds/s3.qmd
40-
- content/git/index.qmd
41-
- content/git/introgit.qmd
42-
- content/git/exogit.qmd
43-
- content/annexes/about.qmd
44-
- content/annexes/evaluation.qmd
45-
- content/annexes/corrections.qmd
468

479
profile:
4810
default: fr

content/manipulation/01_numpy.qmd

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,13 @@ categories:
1212
description: |
1313
`Numpy` constitue la brique de base de l'écosystème de la _data science_ en
1414
`Python`. Toutes les librairies de manipulation de données, de modélisation
15-
et de visualisation reposent, de manière plus ou moins directe, sur `Numpy`.
16-
Il est donc indispensable de revoir quelques notions sur ce package avant
17-
d'aller plus loin.
15+
et de visualisation reposent, de manière plus ou moins directe, sur `Numpy`. Il est donc indispensable de revoir quelques notions sur ce package avant d'aller plus loin.
1816
description-en: |
1917
`Numpy` is the cornerstone of the _data science_ ecosystem in `Python`. All data manipulation, modeling, and visualization libraries rely, directly or indirectly, on `Numpy`. It is therefore essential to review some concepts of this package before moving forward.
2018
image: scatter_numpy.png
2119
echo: false
2220
---
2321

24-
fffffffff
25-
2622
{{< badges
2723
printMessage="true"
2824
>}}
@@ -38,8 +34,7 @@ fffffffff
3834
Ce chapitre constitue une introduction à _Numpy_ pour
3935
s'assurer que les bases du calcul vectoriel avec `Python`
4036
soient maîtrisées. La première partie du chapitre
41-
présente des petits exercices pour pratiquer
42-
quelques fonctions basiques de `Numpy`. La fin du chapitre présente
37+
présente des petits exercices pour pratiquer quelques fonctions basiques de `Numpy`. La fin du chapitre présente
4338
des exercices pratiques d'utilisation de `Numpy` plus approfondis.
4439

4540
Il est recommandé de régulièrement se référer à
@@ -79,36 +74,34 @@ We will also set the seed of the random number generator to obtain reproducible
7974

8075
```{python}
8176
#| echo: true
82-
np.random.seed(12345)
77+
import numpy as np
78+
rng = np.random.default_rng(seed=12345)
8379
```
8480

8581
::: {.content-visible when-profile="fr"}
8682

87-
::: {.callout-note}
88-
89-
Les auteurs de `numpy` [préconisent désormais](https://numpy.org/doc/stable/reference/random/index.html)
90-
de privilégier l'utilisation de générateurs via la fonction `default_rng()` plutôt que la simple utilisation de `numpy.random`.
83+
::: {.callout-caution}
9184

92-
Afin d'être en phase avec les codes qu'on peut trouver partout sur internet, nous conservons encore `np.random.seed` mais cela peut être amené à évoluer.
85+
Historiquement, la génération de nombres aléatoires se faisait pas le biais du package `numpy.random`. Néanmoins, les auteurs de `Numpy` [recommandent maintenant](https://numpy.org/doc/stable/reference/random/index.html) d'utiliser plutôt des générateurs pour cela. Les exemples de ce tutoriel adoptent donc cette pratique.
9386

9487
:::
9588

9689
:::
9790

9891
:::: {.content-visible when-profile="en"}
9992

100-
::: {.callout-note}
93+
::: {.callout-caution}
10194

102-
The authors of `numpy` [now recommend](https://numpy.org/doc/stable/reference/random/index.html) using generators via the `default_rng()` function rather than simply using `numpy.random`.
103-
104-
To stay consistent with the codes found everywhere on the internet, we still use `np.random.seed`, but this may change in the future.
95+
Historically, random numbers were generated using the `numpy.random` package. However, the authors of `Numpy` [now recommend](https://numpy.org/doc/stable/reference/random/index.html) using generators instead. The examples in this tutorial adopt this practice.
10596

10697
:::
10798

10899
::::
109100

110101
::: {.content-visible when-profile="fr"}
111102

103+
104+
112105
# Le concept d'_array_
113106

114107
Dans le monde de la science des données, comme cela sera évoqué
@@ -227,10 +220,10 @@ np.array([["a","z","e"],["r","t"],["y"]], dtype="object")
227220

228221
Il existe aussi des méthodes pratiques pour créer des array:
229222

230-
* séquences logiques : `np.arange` (suite) ou `np.linspace` (interpolation linéaire entre deux bornes)
231-
* séquences ordonnées : _array_ rempli de zéros, de 1 ou d'un nombre désiré : `np.zeros`, `np.ones` ou `np.full`
232-
* séquences aléatoires : fonctions de génération de nombres aléatoires : `np.rand.uniform`, `np.rand.normal`, etc.
233-
* tableau sous forme de matrice identité : `np.eye`
223+
* séquences logiques : `np.arange` (suite) ou `np.linspace` (interpolation linéaire entre deux bornes) ;
224+
* séquences ordonnées : _array_ rempli de zéros, de 1 ou d'un nombre désiré : `np.zeros`, `np.ones` ou `np.full` ;
225+
* séquences aléatoires : fonctions de génération de nombres aléatoires : `rng.uniform`, `rng.normal`, etc.`rng` est un générateur de nombre aléatoires ;
226+
* tableau sous forme de matrice identité : `np.eye`.
234227

235228
Ceci donne ainsi, pour les séquences logiques:
236229

@@ -239,10 +232,10 @@ Ceci donne ainsi, pour les séquences logiques:
239232
::: {.content-visible when-profile="en"}
240233
There are also practical methods for creating arrays:
241234

242-
* Logical sequences: `np.arange` (sequence) or `np.linspace` (linear interpolation between two bounds)
243-
* Ordered sequences: array filled with zeros, ones, or a desired number: `np.zeros`, `np.ones`, or `np.full`
244-
* Random sequences: random number generation functions: `np.rand.uniform`, `np.rand.normal`, etc.
245-
* Matrix in the form of an identity matrix: `np.eye`
235+
* Logical sequences: `np.arange` (sequence) or `np.linspace` (linear interpolation between two bounds);
236+
* Ordered sequences: array filled with zeros, ones, or a desired number: `np.zeros`, `np.ones`, or `np.full`;
237+
* Random sequences: random number generation functions: `rng.uniform`, `rng.normal`, etc. where `rng` is a random number generator;
238+
* Matrix in the form of an identity matrix: `np.eye`.
246239

247240
This gives, for logical sequences:
248241
:::
@@ -432,6 +425,51 @@ The syntax for selecting particular indices from a list also works with arrays.
432425
{{< include "01_numpy_exercises/_exo2_solution.qmd" >}}
433426
:::
434427

428+
::: {.content-visible when-profile="fr"}
429+
430+
La logique se généralise pour les _array_ multidimensionnels. L'indexation se fait alors à plusieurs niveaux. Prenons par exemple un array à 2 dimensions (une matrice en quelques sortes):
431+
432+
```{python}
433+
x = np.array([[1, 2, 3], [4, 5, 6]], np.int32)
434+
```
435+
436+
Si on veut sélectionner la 2e ligne, 3e colonne (l'élément de valeur 6), on fait
437+
438+
```{python}
439+
x[1, 2]
440+
```
441+
442+
Maintenant, pour sélectionner une colonne complète (par exemple la 2e), on peut utiliser le 2e index pour spécifier celle-ci (index 1 en Python puisque l'indexation part de 0) puis `:` sur la première dimension (version raccourcie de `0:N`) pour ne pas discriminer selon cette dimension:
443+
444+
```{python}
445+
x[:,1]
446+
```
447+
448+
Le principe se généralise, mais se complexifie, pour des _array_ imbriqués. Heureusement, ce sont des objets qu'on manipule assez rarement directement, la plupart de nos données numériques étant des tableaux plats (une valeur - l'observation - est le croisement d'une ligne - l'individu - et d'une colonne - la variable).
449+
450+
:::
451+
::: {.content-visible when-profile="en"}
452+
The same logic applies to multidimensional _arrays_. Indexing then takes place at several levels. Take, for example, a 2-dimensional array (a matrix of sorts):
453+
454+
``{python}
455+
x = np.array([[1, 2, 3], [4, 5, 6]], np.int32)
456+
````
457+
458+
If we want to select the 2nd row, 3rd column (the element with value 6), we do
459+
460+
x[1, 2]
461+
````{python}
462+
463+
Now, to select a complete column (e.g. the 2nd), we can use the 2nd index to specify it (index 1 in Python since indexing starts from 0) and then `:` on the first dimension (shortened version of `0:N`) to avoid discriminating according to this dimension:
464+
465+
``{python}
466+
x[:,1]
467+
```
468+
469+
The principle is generalized, but becomes more complex, for nested _arrays_. Fortunately, these are objects we rarely manipulate directly, as most of our numerical data are flat arrays (a value - the observation - is the intersection of a row - the individual - and a column - the variable).
470+
:::
471+
472+
435473
::: {.content-visible when-profile="fr"}
436474
437475
## Sur la performance
@@ -543,7 +581,8 @@ Let's create `x` a multidimensional array and `y` a one-dimensional array with a
543581
544582
```{python}
545583
#| echo: true
546-
x = np.random.normal(0, size=(3, 4))
584+
# Assuming rng has been created beforehand
585+
x = rng.normal(0, size=(3, 4))
547586
y = np.array([np.nan, 0, 1])
548587
```
549588
@@ -605,7 +644,7 @@ To combine arrays, you can use, depending on the case, the functions `np.concate
605644
606645
```{python}
607646
#| echo: true
608-
x = np.random.normal(size = 10)
647+
x = rng.normal(size = 10)
609648
```
610649
611650
::: {.content-visible when-profile="fr"}
@@ -650,7 +689,7 @@ For classical descriptive statistics, `Numpy` offers a number of already impleme
650689
651690
```{python}
652691
#| echo: true
653-
x = np.random.normal(0, size=(3, 4))
692+
x = rng.normal(0, size=(3, 4))
654693
```
655694
656695
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
```{python}
22
#| output: false
3-
X = np.random.uniform(0,1,1000)
4-
Y = np.random.normal(0,np.sqrt(2),1000)
3+
4+
# If rng has not been created beforehand:
5+
# rng = np.random.default_rng()
6+
7+
X = rng.uniform(0,1,1000)
8+
Y = rng.normal(0,np.sqrt(2),1000)
59
610
np.var(Y)
711
```

content/manipulation/01_numpy_exercises/_exo3_solution.qmd

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
```{python}
22
#| output: false
33
4-
# Solution
5-
x = np.random.normal(size=10000)
4+
# If rng has not been created beforehand:
5+
# rng = np.random.default_rng()
6+
7+
x = rng.normal(size=10000)
68
79
x2 = x[np.abs(x)>=1.96]
810

content/manipulation/01_numpy_exercises/_exo4_solution.qmd

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
```{python}
22
#| output: false
33
4-
# Correction
5-
x = np.random.normal(0, size=(3, 4))
4+
# If rng has not been created beforehand:
5+
# rng = np.random.default_rng()
6+
7+
x = rng.normal(0, size=(3, 4))
68
y = np.array([np.nan, 0, 1])
79
810
print(x)

content/manipulation/01_numpy_exercises/_exo6_en.qmd

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
::: {.callout-tip}
2-
## Exercise (a bit more challenging)
2+
## Exercise 6 (a bit more challenging)
33

44
1. Create `X`, a two-dimensional array (i.e., a matrix) with 10 rows and 2 columns. The numbers in the array are random.
55
2. Import the `matplotlib.pyplot` module as `plt`. Use `plt.scatter` to plot the data as a scatter plot.
66
3. Construct a 10x10 matrix storing, at element $(i,j)$, the Euclidean distance between points $X[i,]$ and $X[j,]$. To do this, you will need to work with dimensions by creating nested arrays using `np.newaxis`:
7-
+ First, use `X1 = X[:, np.newaxis, :]` to transform the matrix into a nested array. Check the dimensions.
8-
+ Create `X2` of dimension `(1, 10, 2)` using the same logic.
9-
+ Deduce, for each point, the distance with other points for each coordinate. Square this distance.
10-
+ At this stage, you should have an array of dimension `(10, 10, 2)`. The reduction to a matrix is obtained by summing over the last axis. Check the help of `np.sum` on how to sum over the last axis.
11-
+ Finally, apply the square root to obtain a proper Euclidean distance.
7+
1. First, use `X1 = X[:, np.newaxis, :]` to transform the matrix into a nested array. Check the dimensions.
8+
2. Create `X2` of dimension `(1, 10, 2)` using the same logic.
9+
3. Deduce, for each point, the distance with other points for each coordinate. Square this distance.
10+
4. At this stage, you should have an array of dimension `(10, 10, 2)`. The reduction to a matrix is obtained by summing over the last axis. Check the help of `np.sum` on how to sum over the last axis.
11+
5. Finally, apply the square root to obtain a proper Euclidean distance.
1212
4. Verify that the diagonal elements are zero (distance of a point to itself...).
1313
5. Now, sort for each point the points with the most similar values. Use `np.argsort` to get the ranking of the closest points for each row.
1414
6. We are interested in the k-nearest neighbors. For now, set k=2. Use `argpartition` to reorder each row so that the 2 closest neighbors of each point come first, followed by the rest of the row.

content/manipulation/01_numpy_exercises/_exo6_fr.qmd

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
::: {.callout-tip}
2-
## Exercice (un peu plus corsé)
2+
## Exercice 6 (un peu plus corsé)
33

44

55
1. Créer `X` un tableau à deux dimensions (i.e. une matrice) comportant 10 lignes
66
et 2 colonnes. Les nombres dans le tableau sont aléatoires.
77
2. Importer le module `matplotlib.pyplot` sous le nom `plt`. Utiliser
88
`plt.scatter` pour représenter les données sous forme de nuage de points.
99
3. Constuire une matrice 10x10 stockant, à l'élément $(i,j)$, la distance euclidienne entre les points $X[i,]$ et $X[j,]$. Pour cela, il va falloir jouer avec les dimensions en créant des tableaux emboîtés à partir par des appels à `np.newaxis` :
10-
+ En premier lieu, utiliser `X1 = X[:, np.newaxis, :]` pour transformer la matrice en tableau emboîté. Vérifier les dimensions
11-
+ Créer `X2` de dimension `(1, 10, 2)` à partir de la même logique
12-
+ En déduire, pour chaque point, la distance avec les autres points pour chaque coordonnées. Elever celle-ci au carré
13-
+ A ce stade, vous devriez avoir un tableau de dimension `(10, 10, 2)`. La réduction à une matrice s'obtient en sommant sur le dernier axe. Regarder dans l'aide de `np.sum` comme effectuer une somme sur le dernier axe.
14-
+ Enfin, appliquer la racine carrée pour obtenir une distance euclidienne en bonne et due forme.
10+
1. En premier lieu, utiliser `X1 = X[:, np.newaxis, :]` pour transformer la matrice en tableau emboîté. Vérifier les dimensions
11+
2. Créer `X2` de dimension `(1, 10, 2)` à partir de la même logique
12+
3. En déduire, pour chaque point, la distance avec les autres points pour chaque coordonnées. Elever celle-ci au carré
13+
4. A ce stade, vous devriez avoir un tableau de dimension `(10, 10, 2)`. La réduction à une matrice s'obtient en sommant sur le dernier axe. Regarder dans l'aide de `np.sum` comme effectuer une somme sur le dernier axe.
14+
5. Enfin, appliquer la racine carrée pour obtenir une distance euclidienne en bonne et due forme.
1515
4. Vérifier que les termes diagonaux sont bien nuls (distance d'un point à lui-même...)
1616
5. Il s'agit maintenant de classer, pour chaque point, les points dont les valeurs sont les plus similaires. Utiliser `np.argsort` pour obtenir, pour chaque ligne, le classement des points les plus proches
1717
6. On va s'intéresser aux k-plus proches voisins. Pour le moment, fixons k=2. Utiliser `argpartition` pour réordonner chaque ligne de manière à avoir les 2 plus proches voisins de chaque point d'abord et le reste de la ligne ensuite

content/manipulation/01_numpy_exercises/_exo6_solution.qmd

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
```{python}
22
#| output: false
33
4-
# Correction
4+
# If rng has not been created beforehand:
5+
# rng = np.random.default_rng()
6+
7+
import matplotlib.pyplot as plt
58
69
# Question 1
7-
X = np.random.rand(10, 2)
10+
X = rng.uniform(size = (10, 2))
811
912
# Question 2
10-
import matplotlib.pyplot as plt
1113
print(X[:,0])
1214
print(X[:,1])
1315
plt.scatter(X[:, 0], X[:, 1], s=100)

content/manipulation/01_numpy_exercises/_exo7_fr.qmd

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33

44
`Google` est devenu célèbre grâce à son algorithme `PageRank`. Celui-ci permet, à partir
55
de liens entre sites _web_, de donner un score d'importance à un site _web_ qui va
6-
être utilisé pour évaluer sa centralité dans un réseau.
7-
L'objectif de cet exercice est d'utiliser `Numpy` pour mettre en oeuvre un tel
8-
algorithme à partir d'une matrice d'adjacence qui relie les sites entre eux.
6+
être utilisé pour évaluer sa centralité dans un réseau. L'objectif de cet exercice est d'utiliser `Numpy` pour mettre en oeuvre un tel algorithme à partir d'une matrice d'adjacence qui relie les sites entre eux.
97

10-
1. Créer la matrice suivante avec `numpy`. L'appeler `M`:
8+
1. Créer la matrice suivante avec `Numpy`. L'appeler `M`:
119

1210
$$
1311
\begin{bmatrix}

content/manipulation/01_numpy_exercises/_exo7_solution.qmd

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ ranking of nodes (pages) in the adjacency matrix
2929
"""
3030
3131
import numpy as np
32+
rng = np.random.default_rng()
33+
3234
3335
def pagerank(M, num_iterations: int = 100, d: float = 0.85):
3436
"""PageRank: The trillion dollar algorithm.
@@ -51,7 +53,7 @@ def pagerank(M, num_iterations: int = 100, d: float = 0.85):
5153
5254
"""
5355
N = M.shape[1]
54-
v = np.random.rand(N, 1)
56+
v = rng.uniform(size = (N, 1))
5557
v = v / np.linalg.norm(v, 1)
5658
M_hat = (d * M + (1 - d) / N)
5759
for i in range(num_iterations):

0 commit comments

Comments
 (0)