stack(): usage un peu plus avancé#
import pandas as pd
df = pd.read_csv("data/stack-multicol.csv")
df
| city | postcode | t1_nb | t1_price | t1_junk | t2_nb | t2_price | t2_junk | t3_nb | t3_price | t3_junk | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | London | 90000 | 1 | 1000 | foo | 2 | 2000 | bar | 0 | 0 | none |
| 1 | Paris | 75000 | 0 | 0 | none | 2 | 4000 | tutu | 0 | 0 | none |
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
on voudrait le transformer en ceci
index |
city |
postcode |
type |
attribute |
value |
|---|---|---|---|---|---|
0 |
London |
90000 |
t1 |
nb |
1 |
0 |
London |
90000 |
t1 |
price |
1000 |
0 |
London |
90000 |
t2 |
nb |
2 |
0 |
London |
90000 |
t2 |
price |
2000 |
0 |
Paris |
75000 |
t2 |
nb |
2 |
0 |
Paris |
75000 |
t2 |
price |
4000 |
parce que
on a enlevé tout ce qui concernait les nb==0
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
types = ['t1', 't2', 't3']
attributes = ['nb', 'price', 'junk']
on coupe en deux#
comme dans le premier exercice, on commence par calculer les colonnes qui contiennent les données à retravailler
les colonnes de la partie droite#
on calcule la liste
[ "t1_nb", "t1_price", ...]
à partir du produit cartésien des deux listes
quelque chose comme
for typ in types:
for attribute in attributes:
columns.append(f"{typ}_{attribute}")
# à vous
true_columns = ...
# et maintenant on extrait ces colonnes-là dans une dataframe
df2 = ...
la partie gauche#
# il s'agit maintenant de prendre les autres données
# à vous
df_left = ...
# pour vérification
df_left
Ellipsis
# pour vérification
df2
Ellipsis
on crée un MultiIndex#
c’est le multi index qui va nous permettre de stacker correctement
[indice] pd.MultiIndex.from_product()
# fabriquez un multi-index
multi_index = ...
# adoptez ce multi-index comme index des colonnes
...
Ellipsis
# vérifiez visuellement que l'indexation est correcte
df
| city | postcode | t1_nb | t1_price | t1_junk | t2_nb | t2_price | t2_junk | t3_nb | t3_price | t3_junk | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | London | 90000 | 1 | 1000 | foo | 2 | 2000 | bar | 0 | 0 | none |
| 1 | Paris | 75000 | 0 | 0 | none | 2 | 4000 | tutu | 0 | 0 | none |
df2
Ellipsis
on nettoie (1): junk#
rappelez-vous qu’on ne s’intéressait pas aux données junk
du coup il est temps de nettoyer la table de ces colonnes-là
[note] ceux qui suivent vont trouver une façon de faire qui implique de remonter dans le temps
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
# à vous pour le nettoyage
...
stack()#
à ce stade tout est prêt quasiment pour actionner la magie de stack(), essayez et regardez ce que ça vous donne
# à vous
df3 = ...
df2
Ellipsis
df3
Ellipsis
on nettoie (2): les colonnes vides#
ça n’était’était pas vraiment exprès au départ mais c’est intéressant: aucune ville n’a de t3
# à vous de supprimer les colonnes sans intérêt
...
stack() à nouveau#
maintenant qu’on s’est débarrassés de t3,
on peut stacker à nouveau
comme on avait fait dans stack-simple
et comme dans stack-simple on obtient une série car l’index des colonnes est simple
# à vous
s = ...
les labels#
en première lecture, passez cette question, puis quand vous arriverez à la fin revenez-y pour affiner les labels dans le résultat final
# laissez vide en première lecture
s
Ellipsis
etc…#
essentiellement maintenant, c’est la même logique que dans stack-simple, je vous laisse finir
[indices] reset_index() et join()
# à vous
df_right = ...
# à vous
df_final = ...
df_final
Ellipsis
pas demandé#
# ce n'était pas demandé, mais
# si on veut remettre un index propre, on n'a qu'à faire
df_final.index = pd.RangeIndex(0, len(df_final))
df_final
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[24], line 3
1 # ce n'était pas demandé, mais
2 # si on veut remettre un index propre, on n'a qu'à faire
----> 3 df_final.index = pd.RangeIndex(0, len(df_final))
4 df_final
TypeError: object of type 'ellipsis' has no len()
à quoi ça sert#
# en tous cas, sous cette forme, on peut s'intéresser à un type particulier
df_t1 = df_final.loc[df_final.attribute == 't1', :]
df_t1
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[25], line 2
1 # en tous cas, sous cette forme, on peut s'intéresser à un type particulier
----> 2 df_t1 = df_final.loc[df_final.attribute == 't1', :]
3 df_t1
AttributeError: 'ellipsis' object has no attribute 'loc'
# ou juste les nombres
df_t1_nb = df_t1[df_t1.type == 'nb']
df_t1_nb
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[26], line 2
1 # ou juste les nombres
----> 2 df_t1_nb = df_t1[df_t1.type == 'nb']
3 df_t1_nb
NameError: name 'df_t1' is not defined