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