Skip to content

Commit 068b557

Browse files
committed
light pass on the 3 pandas exos on stack
1 parent a54313d commit 068b557

7 files changed

Lines changed: 143 additions & 65 deletions

notebooks/myst-toc.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ project:
4141
- file: pandas-exos/EXO-mosaique-nb.md
4242
- file: pandas-exos/EXO-titanic-nb.md
4343
- file: pandas-exos/EXO-stack-simple-nb.md
44-
- file: pandas-exos/EXO-bornes-nb.md
4544
- file: pandas-exos/EXO-stack-multicol-nb.md
45+
- file: pandas-exos/EXO-stack-bornes-nb.md
4646
- pattern: pandas-exos/.teacher/EXO-*corrige-nb.md
4747
hidden: true
4848

notebooks/pandas-exos/.teacher/EXO-bornes-corrige-nb.md renamed to notebooks/pandas-exos/.teacher/EXO-stack-bornes-corrige-nb.md

File renamed without changes.

notebooks/pandas-exos/.teacher/EXO-stack-multicol-corrige-nb.md

Lines changed: 68 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,30 @@ kernelspec:
99
name: python3
1010
language_info:
1111
name: python
12-
nbconvert_exporter: python
1312
pygments_lexer: ipython3
13+
nbconvert_exporter: python
1414
nbhosting:
1515
title: stack() multi-colonnes
1616
---
1717

18+
# `stack()`: usage un peu plus avancé
19+
1820
```{code-cell} ipython3
1921
import pandas as pd
2022
```
2123

22-
# `stack()`: usage un peu plus avancé
24+
ceci est une version un peu plus évoluée que dans l'exercice précédent [](#label-exo-stack-simple)
25+
sauf que cette fois-ci, chaque type (t1, t2, t3, ...) est décrit par 3 colonnes
2326

2427
```{code-cell} ipython3
2528
df = pd.read_csv("data/stack-multicol.csv")
2629
df
2730
```
2831

29-
c'est donc une version un peut plus évoluée que dans un exercice précédent (`stack-simple`): chaque type est décrit par 3 colonnes
32+
et notre objectif est de le transformer en ceci
3033

31-
+++
32-
33-
on voudrait le transformer en ceci
34+
```{div}
35+
:label: exo-stack-multicol-target
3436
3537
| index | city | postcode | type| attribute | value |
3638
|-------|------|----------|------|-----------|--------|
@@ -40,15 +42,18 @@ on voudrait le transformer en ceci
4042
|0|London|90000|t2|price|2000|
4143
|0|Paris|75000|t2|nb|2|
4244
|0|Paris|75000|t2|price|4000|
45+
```
4346

4447
+++
4548

46-
parce que
49+
notez bien que
4750

4851
* on a enlevé tout ce qui concernait les nb==0
4952
* on ne se donne pas de spécification précise sur l'index, d'où les 0 mais ça peut être ce qu'on veut
5053

5154
```{code-cell} ipython3
55+
# quelques variables utiles pour la suite
56+
5257
types = ['t1', 't2', 't3']
5358
attributes = ['nb', 'price', 'junk']
5459
```
@@ -69,16 +74,20 @@ comme dans le premier exercice, on commence par calculer les colonnes qui contie
6974

7075
+++
7176

72-
on calcule la liste
77+
on calcule la liste
7378
`[ "t1_nb", "t1_price", ...]`
7479
à partir du produit cartésien des deux listes
7580

81+
````{admonition} indice
82+
:class: dropdown tip
83+
7684
quelque chose comme
7785
```python
7886
for typ in types:
7987
for attribute in attributes:
8088
columns.append(f"{typ}_{attribute}")
8189
```
90+
````
8291

8392
```{code-cell} ipython3
8493
# à vous
@@ -94,7 +103,7 @@ true_columns = ...
94103
# notez qu'on pourrait aussi bien utiliser itertools.product
95104
96105
true_columns = [
97-
f"{typ}_{attribute}"
106+
f"{typ}_{attribute}"
98107
for typ in types for attribute in attributes
99108
]
100109
```
@@ -117,6 +126,7 @@ df2 = df[true_columns]
117126

118127
```{code-cell} ipython3
119128
# il s'agit maintenant de prendre les autres données
129+
# i.e. les colonnes qui ne sont pas dans df2
120130
121131
# à vous
122132
df_left = ...
@@ -137,6 +147,16 @@ for column in true_columns:
137147
del df_left[column]
138148
```
139149

150+
```{code-cell} ipython3
151+
:tags: [level_basic]
152+
153+
# prune-cell
154+
155+
# on pourrait aussi faire comme ceci
156+
left_columns = list(set(df.columns) - set(true_columns))
157+
df_left = df[left_columns]
158+
```
159+
140160
```{code-cell} ipython3
141161
:cell_style: split
142162
@@ -159,7 +179,11 @@ df2
159179

160180
c'est le multi index qui va nous permettre de stacker correctement
161181

162-
**[indice]** `pd.MultiIndex.from_product()`
182+
```{admonition} indice
183+
:class: dropdown tip
184+
185+
voyez `pd.MultiIndex.from_product()`
186+
```
163187

164188
```{code-cell} ipython3
165189
# fabriquez un multi-index
@@ -178,7 +202,7 @@ multi_index = pd.MultiIndex.from_product([types, attributes])
178202
```
179203

180204
```{code-cell} ipython3
181-
# adoptez ce multi-index comme index des colonnes
205+
# adoptez ce multi-index comme index des colonnes de df2
182206
183207
...
184208
```
@@ -194,11 +218,9 @@ df2.columns = multi_index
194218
```
195219

196220
```{code-cell} ipython3
197-
# vérifiez visuellement que l'indexation est correcte
198-
df
199-
```
221+
# vérifiez visuellement que les colonnes sont indexées correctement
222+
200223
201-
```{code-cell} ipython3
202224
df2
203225
```
204226

@@ -209,8 +231,13 @@ df2
209231
rappelez-vous qu'on ne s'intéressait pas aux données `junk`
210232
du coup il est temps de nettoyer la table de ces colonnes-là
211233

212-
**[note]** ceux qui suivent vont trouver une façon de faire qui implique de remonter dans le temps
234+
```{admonition} note - on aurait pu le faire plus tôt
235+
:class: dropdown note
236+
237+
ceux qui suivent vont trouver une façon de faire qui implique de remonter dans le temps
238+
(je veux dire de traiter ce point plus tôt dans le notebook)
213239
c'est vrai qu'on aurait pu faire comme ça, mais essayez tout de même de trouver une façon de le faire maintenant
240+
```
214241

215242
```{code-cell} ipython3
216243
# à vous pour le nettoyage
@@ -221,8 +248,10 @@ c'est vrai qu'on aurait pu faire comme ça, mais essayez tout de même de trouve
221248
:tags: [level_basic]
222249
223250
# prune-cell
224-
# la remontée dans le temps consiste tout simplement à ne paa mentionner
251+
# la remontée dans le temps consiste tout simplement à ne pas mentionner
225252
# 'junk' dans la variable `attributes` au début du notebook
253+
# mais alors on aurait retrouvé ces données dans df_left,
254+
# qu'il faudrait alors calculer autrement...
226255
```
227256

228257
```{code-cell} ipython3
@@ -273,21 +302,25 @@ type(df3), df3
273302
```{code-cell} ipython3
274303
:cell_style: split
275304
305+
# pour vérifier
306+
276307
df2
277308
```
278309

279310
```{code-cell} ipython3
280311
:cell_style: split
281312
313+
# pour vérifier
314+
282315
df3
283316
```
284317

285318
## on nettoie (2): les colonnes vides
286319

287320
+++
288321

289-
ça n'était'était pas vraiment exprès au départ
290-
mais c'est intéressant: aucune ville n'a de t3
322+
ça n'était pas vraiment délibéré au départ
323+
mais le cas est intéressant: aucune ville n'a de t3
291324

292325
```{code-cell} ipython3
293326
# à vous de supprimer les colonnes sans intérêt
@@ -368,14 +401,18 @@ s
368401

369402
+++
370403

371-
essentiellement maintenant, c'est la même logique que dans `stack-simple`, je vous laisse finir
404+
essentiellement maintenant, c'est la même logique que dans l'exercice [](#label-exo-stack-simple), je vous laisse finir [pour obtenir le résultat souhaité](#exo-stack-multicol-target)
372405

373-
**[indices]** `reset_index()` et `join()`
406+
```{admonition} indice
407+
:class: dropdown tip
408+
409+
voir `reset_index()` et `join()`
410+
```
374411

375412
```{code-cell} ipython3
376413
# à vous
377414
378-
df_right = ...
415+
df_final = ...
379416
```
380417

381418
```{code-cell} ipython3
@@ -391,12 +428,6 @@ df_right = s.reset_index(level=(1, 2))
391428
type(df_right), df_right
392429
```
393430

394-
```{code-cell} ipython3
395-
# à vous
396-
397-
df_final = ...
398-
```
399-
400431
```{code-cell} ipython3
401432
:tags: [level_basic]
402433
@@ -421,24 +452,29 @@ df_final
421452
422453
# ce n'était pas demandé, mais
423454
# si on veut remettre un index propre, on n'a qu'à faire
455+
424456
df_final.index = pd.RangeIndex(0, len(df_final))
425457
df_final
426458
```
427459

428-
## à quoi ça sert
460+
## à quoi ça sert ?
461+
462+
les usages pour ce type de traitement sont nombreux, par exemple
429463

430464
```{code-cell} ipython3
431465
:tags: [raises-exception]
432466
433-
# en tous cas, sous cette forme, on peut s'intéresser à un type particulier
434-
df_t1 = df_final.loc[df_final.attribute == 't1', :]
467+
# sous cette forme, on peut s'intéresser à un type particulier
468+
469+
df_t1 = df_final.loc[df_final.type == 't1', :]
435470
df_t1
436471
```
437472

438473
```{code-cell} ipython3
439474
:tags: [raises-exception]
440475
441476
# ou juste les nombres
442-
df_t1_nb = df_t1[df_t1.type == 'nb']
477+
478+
df_t1_nb = df_t1[df_t1.attribute == 'nb']
443479
df_t1_nb
444480
```

notebooks/pandas-exos/.teacher/EXO-stack-simple-corrige-nb.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ nbhosting:
1515
title: stack() simple
1616
---
1717

18+
(label-exo-stack-simple)=
1819
# `stack()`: usage typique
1920

2021
```{code-cell} ipython3
@@ -112,9 +113,12 @@ series
112113

113114
+++
114115

115-
à ce stade, que faut-il faire avec la donnée `type` pour se rapprocher de ce qu'on cherche à produire ?
116+
maintenant, que faut-il faire avec la donnée `type` pour se rapprocher de ce qu'on cherche à produire ?
116117

117-
**[indice]** voyez `df.reset_index()`
118+
```{admonition} indice
119+
:class: dropdown tip
120+
voyez `df.reset_index()`
121+
```
118122

119123
```{code-cell} ipython3
120124
# à vous
@@ -166,10 +170,15 @@ df3
166170

167171
à ce stade il ne reste plus qu'à recoller les morceaux
168172

169-
**[indice]** `pd.merge()` et/ou `df.join()`
173+
```{admonition} indice
174+
:class: dropdown tip
175+
voyez `pd.merge()` et/ou `df.join()`
176+
```
170177

171178
```{code-cell} ipython3
172179
# à vous
180+
181+
df_all = ...
173182
```
174183

175184
```{code-cell} ipython3
File renamed without changes.

0 commit comments

Comments
 (0)