[PYTHON] Comment utiliser MultiIndex (mémorandum personnel)

Qu'est-ce que MultiIndex

Cliquez ici pour plus de détails ↓ https://pandas.pydata.org/pandas-docs/stable/user_guide/advanced.html Selon le document, il s'agit d'un index hiérarchique et peut être utilisé lors de la manipulation de données de grande dimension (en gros).

Le panneau qui gère la structure de données 3D dans les pandas a été aboli, alors vérifiez comment le gérer ici. Puisqu'il s'agit d'un mémorandum personnel, il n'est pas du tout exhaustif. Par conséquent, si vous avez des questions, vous devez enquêter le cas échéant.

Environnement etc.

python 3.7.7 pandas 1.1.1 Environnement d'exécution: notebook jupyter

Confirmation des données

Comme prévu, les données de recherche ne peuvent pas être utilisées, donc des échantillons de données seront créés de manière appropriée.

Créer des données

#importation de pandas
import pandas as pd

#Création de données
array =[['cat','cat','cat','cat','cat','dog','dog','dog','bird','bird'],
        ['black','white','white','brown','brown','black','white','brown','white','yellow'],
        ['male','male','female','male','female','female','female','male','male','female'],
        [3,5,5,5,4,7,8,10,1,2], 
        [20,25,26,30,22,77,55,90,10,15], 
        [3.6,4.5,4.0,5.2,3.0,15.6,10.5,20.1,0.52,0.89]]

#Convertir en DataFrame.Inversion des lignes et des colonnes avec T
df = pd.DataFrame(array).T

#paramètres de colonne
df.columns = ['animal','color','male or female','age','height','weight']

Contenu des données

Comme ça. Puisque le contenu est créé implicitement, il semble y avoir un chat très obèse.

animal color male or female age height weight
0 cat black male 3 20 3.6
1 cat white male 5 25 4.5
2 cat white female 5 26 4
3 cat brown male 5 30 5.2
4 cat brown female 4 22 3
5 dog black female 7 77 15.6
6 dog white female 8 55 10.5
7 dog brown male 10 90 20.1
8 bird white male 1 10 0.52
9 bird yellow female 2 15 0.89

A part: Vous pouvez utiliser .to_markdown () pour créer une table de notation markdown. Il semble qu'il a été implémenté à partir de la version 1.0.0 ou ultérieure des pandas? Cependant, au final, .to_html () est redevable.

Utilisation de base

index Comment définir et réinitialiser l'index

réglage de l'index

Le nom de colonne spécifié par set_index est l'indice du niveau à partir de 0 à partir de animal. level→0 : animal, 1 : color, 2 : male or female


df2 = df.set_index(['animal','color','male or female'])
age height weight
animal color male or female
cat black male 3 20 3.6
white male 5 25 4.5
female 5 26 4
brown male 5 30 5.2
female 4 22 3
dog black female 7 77 15.6
white female 8 55 10.5
brown male 10 90 20.1
bird white male 1 10 0.52
yellow female 2 15 0.89

En passant, les niveaux d'index peuvent être définis dans l'ordre de votre choix.

df3 = df.set_index(['animal','male or female','color'])
age height weight
animal male or female color
cat male black 3 20 3.6
white 5 25 4.5
female white 5 26 4
male brown 5 30 5.2
female brown 4 22 3
dog female black 7 77 15.6
white 8 55 10.5
male brown 10 90 20.1
bird male white 1 10 0.52
female yellow 2 15 0.89

En comparant avec le tableau ci-dessus, on peut confirmer que les valeurs des premier et second niveaux sont interchangées.

En remarque, .set_index () a drop comme paramètre, qui est True par défaut. Ceci spécifie s'il faut supprimer les données de la colonne utilisée comme index. Par conséquent, lorsque drop = False, les données de la colonne spécifiée dans Index restent telles quelles, comme indiqué ci-dessous.

df4 = df.set_index(['animal','color','male or female'], drop=False)
                                                                                                                                                                                                                                                 
animalcolormale or femaleageheightweight
animalcolormale or female
catblackmalecatblackmale3203.6
whitemalecatwhitemale5254.5
femalecatwhitefemale5264
brownmalecatbrownmale5305.2
femalecatbrownfemale4223
dogblackfemaledogblackfemale77715.6
whitefemaledogwhitefemale85510.5
brownmaledogbrownmale109020.1
birdwhitemalebirdwhitemale1100.52
yellowfemalebirdyellowfemale 2 15 0.89

Comme ça. Fondamentalement, il semble qu'il n'y ait aucun problème avec la valeur par défaut, vous n'avez donc pas à vous en soucier.

Réinitialisation de l'index

Pour réinitialiser l'index, utilisez .reset_index ().

df1 = df2.reset_index()

Si vous comparez df et df1, vous pouvez voir que le tableau est le même.

prime

Confirmation que le nom de colonne spécifié dans Index est susceptible d'être inclus dans les noms.

df2.index

>
MultiIndex([( 'cat',  'black',   'male'),
            ( 'cat',  'white',   'male'),
            ( 'cat',  'white', 'female'),
            ( 'cat',  'brown',   'male'),
            ( 'cat',  'brown', 'female'),
            ( 'dog',  'black', 'female'),
            ( 'dog',  'white', 'female'),
            ( 'dog',  'brown',   'male'),
            ('bird',  'white',   'male'),
            ('bird', 'yellow', 'female')],
           names=['animal', 'color', 'male or female'])

Je me demande s'il peut être utilisé lors de la vérification du nom de la colonne dans Index.

df2.index.names

>
FrozenList(['animal', 'color', 'male or female'])

Extraction de données

De là, nous utiliserons df2 pour voir diverses choses.

Extraction de valeurs contenues dans un niveau spécifique

Utilisez .index.get_level_values (). Cela renverra une étiquette d'un niveau spécifique en tant que vecteur.

#Spécifié par un nom de colonne de niveau spécifique
df2.index.get_level_values('animal')

> Index(['cat', 'cat', 'cat', 'cat', 'cat', 'dog', 'dog', 'dog', 'bird', 'bird'], dtype='object', name='animal')

Même résultat que ci-dessus ↓

#Peut également être spécifié par numéro de niveau
df2.index.get_level_values(0)

> Index(['cat', 'cat', 'cat', 'cat', 'cat', 'dog', 'dog', 'dog', 'bird', 'bird'], dtype='object', name='animal')

Évitez la duplication avec set, convertissez en liste et triez-la pour créer une nouvelle liste. Si vous souhaitez utiliser l'ordre décroissant, définissez l'argument reverse sur True. (Je ne pense pas que cela ait beaucoup de sens ici.)

Extraire les étiquettes sans duplication

#Obtenez une étiquette sans duplication
a = sorted(list(set(df2.index.get_level_values('animal'))))
a

> ['bird', 'cat', 'dog']

Extraire les valeurs en utilisant .xs ()

En utilisant .xs (), vous pouvez spécifier le nom de la colonne d'index et sa valeur (étiquette) pour la sélection ou l'extraction.

Utilisons la liste créée précédemment pour vérifier le fonctionnement de xs (). Le contenu est ['oiseau', 'chat', 'chien'] ← En utilisant les valeurs de cette liste comme clés, trouvez la taille moyenne de chaque animal mâle et femelle.

M = {}
F = {}

for s in a:
    m = df2['height'].xs([s, 'male'], level=['animal', 'male or female']).mean()
    M[s] = m
    f = df2['height'].xs([s, 'female'], level=['animal', 'male or female']).mean()
    F[s] = f

#résultat
M
> {'bird': 10.0, 'cat': 25.0, 'dog': 90.0}
F
> {'bird': 15.0, 'cat': 24.0, 'dog': 66.0}

En plus de .mean (), .min (), .max (), .std (), .count (), etc. peuvent être utilisés selon le but.

Pour le moment, commentaire

Tout d'abord, spécifiez le nom de la colonne de la valeur que vous voulez trouver (cette fois, je veux connaître la moyenne de 'hauteur') df2['height']

Ensuite, utilisez .xs () pour définir des spécifications détaillées. df2['height'].xs([s, 'male'], level=['animal', 'male or female'])

Premièrement, à propos de [s, 'male']. Cette fois, afin de calculer la taille moyenne de chaque mâle (mâle) et femelle (femelle) de chaque animal, spécifiez une étiquette correspondant à l'information "quel animal et quel sexe" dans le premier argument de .xs ().

Ensuite, à propos de level = ['animal', 'male or female']. Cela semble indiquer le niveau du [s, 'mâle'] spécifié précédemment. Donc, ce serait bien si vous pouviez correspondre au sentiment d'être "animal" et "masculin" chez "homme ou femme". Puisque le niveau peut être spécifié par un nombre, le résultat est le même même si level = [0,2].

Enfin, je veux trouver la moyenne, alors ajoutez .mean ().

Le contenu du dictionnaire ressemble à ceci ↓

#Dans le programme ci-dessus.mean()Retirer et exécuter
m = df2['height'].xs([s, 'male'], level=['animal', 'male or female'])

#résultat
M
> 
{'bird': color
         white    10
 Name: height, dtype: object,
 'cat': color
         black    20
         white    25
         brown    30
 Name: height, dtype: object,
 'dog': color
         brown    90
 Name: height, dtype: object}

Pour chaque animal, la valeur de «hauteur» correspondant au mâle (mâle) peut être obtenue.

Extraire les valeurs à l'aide de .loc

Dans l'ordre, j'ai senti que je devais d'abord vérifier d'ici. Je pense que l'utilisation de .loc est la même que pour un DataFrame normal qui n'est pas Multiindex.

Examen des données

df2
>
                             age height weight
animal color  male or female                  
cat    black  male             3     20    3.6
       white  male             5     25    4.5
              female           5     26      4
       brown  male             5     30    5.2
              female           4     22      3
dog    black  female           7     77   15.6
       white  female           8     55   10.5
       brown  male            10     90   20.1
bird   white  male             1     10   0.52
       yellow female           2     15   0.89

Pour Index, spécifiez "chat" de "animal". Spécifiez tous les noms de colonne de Column.

df2.loc['cat']
#Ou
# df2.loc['cat', :]
>
                     age height weight
color male or female                  
black male             3     20    3.6
white male             5     25    4.5
      female           5     26      4
brown male             5     30    5.2
      female           4     22      3

Vous ne pouvez spécifier que les noms de colonne de Colonne que vous souhaitez affiner.

df2.loc['cat', ['height', 'weight']]
>
                     height weight
color male or female              
black male               20    3.6
white male               25    4.5
      female             26      4
brown male               30    5.2
      female             22      3

Le premier argument est le libellé d'un niveau spécifique d'index et le deuxième argument est le nom de colonne de la colonne que vous souhaitez affiner.

df2.loc['cat', 'height']
>
color  male or female
black  male              20
white  male              25
       female            26
brown  male              30
       female            22
Name: height, dtype: object

Spécifiez plusieurs étiquettes dans le même niveau d'index.

df2.loc[['cat', 'bird'], 'height']
>
animal  color   male or female
cat     black   male              20
        white   male              25
                female            26
        brown   male              30
                female            22
bird    white   male              10
        yellow  female            15
Name: height, dtype: object

Cette fois, comment franchir le niveau d'index. Affinez-vous par ordre de niveau d'index (à partir de 0 en termes de nombres). Si rien n'est spécifié dans (), le résultat est le même que df2.loc [:, 'height'].

# 'cat'Quel est.
df2.loc[('cat'), 'height']
>
color  male or female
black  male              20
white  male              25
       female            26
brown  male              30
       female            22
Name: height, dtype: object


# 'cat'De'white'Quel est.
df2.loc[('cat','white'), 'height']
>
male or female
male      25
female    26
Name: height, dtype: object


# 'cat'De'white'Est'male'Quel est.
df2.loc[('cat','white','male'), 'height']
> 25

Bonus: attribution de valeur

Si vous vous restreignez à ce point, vous pouvez réécrire la valeur.

df3 = df2.copy()
#Suppléant 30
df3.loc[('cat','white','male'), 'height'] = 30

df3.loc[('cat','white','male'), 'height']
> 30

Spécifier par tranche et notes

Il semble que les tranches peuvent également être utilisées, mais si vous le faites sans réfléchir, l'erreur suivante se produira

df2.loc[('cat','brown','male'):('dog','black','female')]

> UnsortedIndexError: 'Key length (3) was greater than MultiIndex lexsort depth (0)'

Solution Trier à l'aide de .sort_index ().

df5 = df2.sort_index(level=0)
df5
>
                             age height weight
animal color  male or female                  
bird   white  male             1     10   0.52
       yellow female           2     15   0.89
cat    black  male             3     20    3.6
       brown  female           4     22      3
              male             5     30    5.2
       white  female           5     26      4
              male             5     25    4.5
dog    black  female           7     77   15.6
       brown  male            10     90   20.1
       white  female           8     55   10.5

Spécifiez niveau = nombre comme argument. Puisque le niveau = 0 a été spécifié cette fois, il est trié en fonction de l'étiquette de l'animal.

df5.loc[('cat','brown','male'):('dog','black','female')]
>
                            age height weight
animal color male or female                  
cat    brown male             5     30    5.2
       white female           5     26      4
             male             5     25    4.5
dog    black female           7     77   15.6

('cat', 'brown'): la plage est réduite à ('dog', 'white').

pd.indexSlice

idx = pd.IndexSlice
df5.loc[idx[:, :, ['male']], 'height']
>
 animal  color  male or female
bird    white  male              10
cat     black  male              20
        brown  male              30
        white  male              25
dog     brown  male              90
Name: height, dtype: object

En regardant uniquement le résultat de sortie, la taille mâle de chaque animal peut être extraite comme dans le cas de l'utilisation de .xs (). Donc, si vous voulez obtenir le même résultat qu'en utilisant .xs (), faites ceci. a = ['bird', 'cat', 'dog']

# pd.Utiliser la tranche d'index
M_idx = {}
for s in a:
    M_idx[s] = df5.loc[idx[[s], :, ['male']], 'height'].mean()
M_idx
> {'bird': 10.0, 'cat': 25.0, 'dog': 90.0}

Comparaison avec l'utilisation de .xs ()

# .xs()utilisation
M = {}
for s in a:
    M[s] = df2['height'].xs([s, 'male'], level=['animal', 'male or female']).mean()
M
> {'bird': 10.0, 'cat': 25.0, 'dog': 90.0}

Lequel utiliser semble être une préférence personnelle

en conclusion

Je pense que Multiindex peut être utilisé de différentes manières une fois que je m'y suis habitué, mais je ne sais toujours pas comment l'utiliser. Plus tard, il peut y avoir des fluctuations typographiques ou des erreurs typographiques que j'ai négligées, je vais donc les corriger.

Site de référence

MultiIndex / advanced indexing

Recommended Posts

Comment utiliser MultiIndex (mémorandum personnel)
Comment utiliser cron (mémo personnel)
Mémorandum sur l'utilisation du python gremlin
Comment utiliser xml.etree.ElementTree
Comment utiliser virtualenv
Comment utiliser Seaboan
Comment utiliser la correspondance d'image
Comment utiliser le shogun
Comment utiliser Pandas 2
Comment utiliser Virtualenv
Comment utiliser numpy.vectorize
Comment utiliser pytest_report_header
Comment utiliser partiel
Comment utiliser SymPy
Comment utiliser x-means
Comment utiliser WikiExtractor.py
Comment utiliser IPython
Comment utiliser virtualenv
Comment utiliser Matplotlib
Comment utiliser iptables
Comment utiliser numpy
Comment utiliser TokyoTechFes2015
Comment utiliser venv
Comment utiliser le dictionnaire {}
Comment utiliser Pyenv
Comment utiliser la liste []
Comment utiliser python-kabusapi
Comment utiliser OptParse
Comment utiliser pyenv-virtualenv
Comment utiliser imutils
Comment utiliser la recherche triée
[gensim] Comment utiliser Doc2Vec
Comprendre comment utiliser django-filter
Comment utiliser le générateur
[Python] Comment utiliser la liste 1
Comment utiliser FastAPI ③ OpenAPI
Comment utiliser Python Argparse
Comment utiliser IPython Notebook
Comment utiliser Pandas Rolling
[Note] Comment utiliser virtualenv
Comment utiliser les dictionnaires redis-py
Python: comment utiliser pydub
[Python] Comment utiliser checkio
[Aller] Comment utiliser "... (3 périodes)"
Comment faire fonctionner GeoIp2 de Django
[Python] Comment utiliser input ()
Comment utiliser le décorateur
[Introduction] Comment utiliser open3d
Comment utiliser Python lambda
Comment utiliser Jupyter Notebook
[Python] Comment utiliser virtualenv
python3: Comment utiliser la bouteille (3)
Comment utiliser Google Colaboratory
Comment utiliser les octets Python
Python: comment utiliser async avec
Comment utiliser la fonction zip
Comment utiliser le module optparse
Résumé de l'utilisation de pandas.DataFrame.loc
Comment installer et utiliser Tesseract-OCR