web-dev-qa-db-fra.com

Pandas: Modifier un niveau particulier de Multiindex

J'ai une trame de données avec Multiindex et je voudrais modifier un niveau particulier du Multiindex. Par exemple, le premier niveau peut être des chaînes et je peux supprimer les espaces blancs de ce niveau d'index:

df.index.levels[1] = [x.replace(' ', '') for x in df.index.levels[1]]

Cependant, le code ci-dessus entraîne une erreur:

TypeError: 'FrozenList' does not support mutable operations.

Je sais que je peux réinitialiser_index et modifier la colonne, puis recréer le Multiindex, mais je me demande s'il existe un moyen plus élégant de modifier directement un niveau particulier du Multiindex.

28
user1642513

Grâce au commentaire de @ cxrodgers, je pense que le moyen le plus rapide de le faire est:

df.index = df.index.set_levels(df.index.levels[0].str.replace(' ', ''), level=0)

Vieille réponse plus longue:

J'ai trouvé que la compréhension de la liste suggérée par @Shovalt fonctionne mais me semblait lente sur ma machine (en utilisant une trame de données avec> 10 000 lignes).

Au lieu de cela, j'ai pu utiliser .set_levels méthode, qui était un peu plus rapide pour moi.

%timeit pd.MultiIndex.from_tuples([(x[0].replace(' ',''), x[1]) for x in df.index])
1 loop, best of 3: 394 ms per loop

%timeit df.index.set_levels(df.index.get_level_values(0).str.replace(' ',''), level=0)
10 loops, best of 3: 134 ms per loop

En réalité, je devais juste ajouter du texte. C'était encore plus rapide avec .set_levels:

%timeit pd.MultiIndex.from_tuples([('00'+x[0], x[1]) for x in df.index])
100 loops, best of 3: 5.18 ms per loop

%timeit df.index.set_levels('00'+df.index.get_level_values(0), level=0)
1000 loops, best of 3: 1.38 ms per loop

%timeit df.index.set_levels('00'+df.index.levels[0], level=0)
1000 loops, best of 3: 331 µs per loop

Cette solution est basée sur la réponse dans le lien du commentaire de @denfromufa ...

python - Multiindex et fuseau horaire - Erreur de liste gelée - Débordement de pile

15
John

Comme mentionné dans les commentaires, les index sont immuables et doivent être refaits lors de la modification, mais vous n'avez pas besoin d'utiliser reset_index pour cela, vous pouvez créer directement un nouveau multi-index:

df.index = pd.MultiIndex.from_tuples([(x[0], x[1].replace(' ', ''), x[2]) for x in df.index])

Cet exemple concerne un index à 3 niveaux, dans lequel vous souhaitez modifier le niveau intermédiaire. Vous devez modifier la taille du tuple pour différentes tailles de niveau.

14
Shovalt