105 votes

Quels sont les arguments " levels ", " keys " et " names " de la fonction concat de Pandas ?

Questions

  • Comment puis-je utiliser pd.concat ?
  • Quel est le levels argument pour ?
  • Quel est le keys argument pour ?
  • Y a-t-il un tas d'exemples pour expliquer comment utiliser tous les arguments ?

Les pandas concat est la fonction Couteau de l'armée suisse des services publics qui fusionnent. Les situations dans lesquelles il est utile sont nombreuses. La documentation existante laisse de côté quelques détails sur certains des arguments optionnels. Parmi eux, on trouve le levels et keys arguments. J'ai cherché à comprendre ce que font ces arguments.

Je vais poser une question qui servira de passerelle vers de nombreux aspects de la pd.concat .

Considérons les trames de données d1 , d2 et d3 :

import pandas as pd

d1 = pd.DataFrame(dict(A=.1, B=.2, C=.3), [2, 3])
d2 = pd.DataFrame(dict(B=.4, C=.5, D=.6), [1, 2])
d3 = pd.DataFrame(dict(A=.7, B=.8, D=.9), [1, 3])

Si je devais concaténer ceux-ci avec

pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'])

J'obtiens le résultat attendu avec un pandas.MultiIndex pour mon columns objet :

        A    B    C    D
d1 2  0.1  0.2  0.3  NaN
   3  0.1  0.2  0.3  NaN
d2 1  NaN  0.4  0.5  0.6
   2  NaN  0.4  0.5  0.6
d3 1  0.7  0.8  NaN  0.9
   3  0.7  0.8  NaN  0.9

Cependant, je voulais utiliser le levels documentation des arguments :

niveaux liste de séquences, par défaut None. Niveaux spécifiques (valeurs uniques) à utiliser pour construire un MultiIndex. Sinon, ils seront déduits des clés.

Alors j'ai passé

pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2']])

Et obtenir un KeyError

ValueError: Key d3 not in level Index(['d1', 'd2'], dtype='object')

C'était logique. Les niveaux que j'ai passés étaient inadéquats pour décrire les niveaux nécessaires indiqués par les clés. Si je n'avais rien passé, comme je l'ai fait ci-dessus, les niveaux sont déduits (comme indiqué dans la documentation). Mais comment puis-je utiliser cet argument à meilleur escient ?

Si j'essayais ça à la place :

pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2', 'd3']])

J'ai obtenu les mêmes résultats que ci-dessus. Mais lorsque j'ajoute une valeur supplémentaire aux niveaux,

df = pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2', 'd3', 'd4']])

Je me retrouve avec le même cadre de données, mais le résultat est le suivant MultiIndex a un niveau inutilisé.

df.index.levels[0]

Index(['d1', 'd2', 'd3', 'd4'], dtype='object')

Alors quel est l'intérêt de la level et devrais-je utiliser l'argument keys différemment ?

J'utilise Python 3.6 et Pandas 0.22.

146voto

piRSquared Points 159

En répondant à cette question par moi-même, j'ai appris beaucoup de choses, et j'ai voulu réunir un catalogue d'exemples et quelques explications.

La réponse spécifique au point de la levels L'argument viendra vers la fin.

pandas.concat : Le manuel manquant

Lien vers la documentation actuelle

Importation et définition d'objets

import pandas as pd

d1 = pd.DataFrame(dict(A=.1, B=.2, C=.3), index=[2, 3])
d2 = pd.DataFrame(dict(B=.4, C=.5, D=.6), index=[1, 2])
d3 = pd.DataFrame(dict(A=.7, B=.8, D=.9), index=[1, 3])

s1 = pd.Series([1, 2], index=[2, 3])
s2 = pd.Series([3, 4], index=[1, 2])
s3 = pd.Series([5, 6], index=[1, 3])

Arguments

objs

Le premier argument que nous rencontrons est objs :

Objets : une séquence ou un mappage d'objets Series, DataFrame ou Panel Si un dict est passé, les clés triées seront utilisées comme argument keys, sauf si un dict est passé, auquel cas les valeurs seront sélectionnées (voir ci-dessous). Tous les objets None seront supprimés silencieusement, sauf s'ils sont tous None, auquel cas une ValueError sera générée.

  • On utilise généralement cette méthode avec une liste de Series ou DataFrame objets.
  • Je vais montrer que dict peut également être très utile.
  • Des générateurs peuvent également être utilisés et peuvent être utiles lors de l'utilisation de map dans le cas de map(f, list_of_df)

Pour l'instant, nous nous contenterons d'une liste de quelques-uns des éléments suivants DataFrame et Series définis ci-dessus. Je montrerai comment les dictionnaires peuvent être exploités pour donner des résultats très utiles MultiIndex les résultats plus tard.

pd.concat([d1, d2])

     A    B    C    D
2  0.1  0.2  0.3  NaN
3  0.1  0.2  0.3  NaN
1  NaN  0.4  0.5  0.6
2  NaN  0.4  0.5  0.6

axis

Le deuxième argument que nous rencontrons est axis dont la valeur par défaut est 0 :

axe : {0/'index', 1/'colonnes'}, par défaut 0 L'axe à concaténer.

Deux DataFrame s avec axis=0 (empilé)

Pour les valeurs de 0 ou index nous voulons dire : "Aligner le long des colonnes et ajouter à l'index".

Comme indiqué ci-dessus où nous avons utilisé axis=0 parce que 0 est la valeur par défaut, et nous voyons que l'indice de d2 prolonge l'indice de d1 malgré un chevauchement de la valeur 2 :

pd.concat([d1, d2], axis=0)

     A    B    C    D
2  0.1  0.2  0.3  NaN
3  0.1  0.2  0.3  NaN
1  NaN  0.4  0.5  0.6
2  NaN  0.4  0.5  0.6

Deux DataFrame s avec axis=1 (côte à côte)

Pour les valeurs 1 ou columns nous voulons dire : "Aligner le long de l'index et ajouter aux colonnes",

pd.concat([d1, d2], axis=1)

     A    B    C    B    C    D
1  NaN  NaN  NaN  0.4  0.5  0.6
2  0.1  0.2  0.3  0.4  0.5  0.6
3  0.1  0.2  0.3  NaN  NaN  NaN

Nous pouvons voir que l'index résultant est l'union des index et que les colonnes résultantes sont l'extension des colonnes de l'index. d1 par les colonnes de d2 .

Deux (ou trois) Series avec axis=0 (empilé)

En combinant pandas.Series le long de axis=0 nous obtenons un pandas.Series . Le nom du fichier résultant Series sera None à moins que tous les Series qui sont combinés portent le même nom. Faites attention à la 'Name: A' lorsque nous imprimons le résultat Series . Lorsqu'il n'est pas présent, on peut supposer que la Series le nom est None .

               |                       |                        |  pd.concat(
               |  pd.concat(           |  pd.concat(            |      [s1.rename('A'),
 pd.concat(    |      [s1.rename('A'), |      [s1.rename('A'),  |       s2.rename('B'),
     [s1, s2]) |       s2])            |       s2.rename('A')]) |       s3.rename('A')])
-------------- | --------------------- | ---------------------- | ----------------------
2    1         | 2    1                | 2    1                 | 2    1
3    2         | 3    2                | 3    2                 | 3    2
1    3         | 1    3                | 1    3                 | 1    3
2    4         | 2    4                | 2    4                 | 2    4
dtype: int64   | dtype: int64          | Name: A, dtype: int64  | 1    5
               |                       |                        | 3    6
               |                       |                        | dtype: int64

Deux (ou trois) Series avec axis=1 (côte à côte)

En combinant pandas.Series le long de axis=1 c'est le name auquel nous nous référons pour déduire le nom d'une colonne dans le résultat de la recherche pandas.DataFrame .

                       |                       |  pd.concat(
                       |  pd.concat(           |      [s1.rename('X'),
 pd.concat(            |      [s1.rename('X'), |       s2.rename('Y'),
     [s1, s2], axis=1) |       s2], axis=1)    |       s3.rename('Z')], axis=1)
---------------------- | --------------------- | ------------------------------
     0    1            |      X    0           |      X    Y    Z
1  NaN  3.0            | 1  NaN  3.0           | 1  NaN  3.0  5.0
2  1.0  4.0            | 2  1.0  4.0           | 2  1.0  4.0  NaN
3  2.0  NaN            | 3  2.0  NaN           | 3  2.0  NaN  6.0

Mixte Series et DataFrame avec axis=0 (empilé)

Lorsque vous effectuez une concaténation d'un Series et DataFrame le long de axis=0 nous convertissons tous les Series à une seule colonne DataFrame s.

Notez bien que c'est une concaténation le long de axis=0 cela signifie étendre l'index (rangées) tout en alignant les colonnes. Dans les exemples ci-dessous, nous voyons que l'index devient [2, 3, 2, 3] qui est une addition sans discernement d'indices. Les colonnes ne se chevauchent pas, à moins que je ne force l'attribution d'un nom à l'index. Series avec l'argument de to_frame :

 pd.concat(               |
     [s1.to_frame(), d1]) |  pd.concat([s1, d1])
------------------------- | ---------------------
     0    A    B    C     |      0    A    B    C
2  1.0  NaN  NaN  NaN     | 2  1.0  NaN  NaN  NaN
3  2.0  NaN  NaN  NaN     | 3  2.0  NaN  NaN  NaN
2  NaN  0.1  0.2  0.3     | 2  NaN  0.1  0.2  0.3
3  NaN  0.1  0.2  0.3     | 3  NaN  0.1  0.2  0.3

Vous pouvez voir les résultats de pd.concat([s1, d1]) sont les mêmes que si j'avais perfromé les to_frame moi-même.

Cependant, je peux contrôler le nom de la colonne résultante avec un paramètre de la fonction to_frame . Renommer le Series avec le rename La méthode fait pas contrôler le nom de la colonne dans le résultat DataFrame .

 # Effectively renames       |                            |
 # `s1` but does not align   |  # Does not rename.  So    |  # Renames to something
 # with columns in `d1`      |  # Pandas defaults to `0`  |  # that does align with `d1`
 pd.concat(                  |  pd.concat(                |  pd.concat(
     [s1.to_frame('X'), d1]) |      [s1.rename('X'), d1]) |      [s1.to_frame('B'), d1])
---------------------------- | -------------------------- | ----------------------------
     A    B    C    X        |      0    A    B    C      |      A    B    C
2  NaN  NaN  NaN  1.0        | 2  1.0  NaN  NaN  NaN      | 2  NaN  1.0  NaN
3  NaN  NaN  NaN  2.0        | 3  2.0  NaN  NaN  NaN      | 3  NaN  2.0  NaN
2  0.1  0.2  0.3  NaN        | 2  NaN  0.1  0.2  0.3      | 2  0.1  0.2  0.3
3  0.1  0.2  0.3  NaN        | 3  NaN  0.1  0.2  0.3      | 3  0.1  0.2  0.3

Mixte Series et DataFrame avec axis=1 (côte à côte)

C'est assez intuitif. Series Le nom de la colonne est par défaut une énumération de ces colonnes. Series lorsqu'un name n'est pas disponible.

                    |  pd.concat(
 pd.concat(         |      [s1.rename('X'),
     [s1, d1],      |       s2, s3, d1],
     axis=1)        |      axis=1)
------------------- | -------------------------------
   0    A    B    C |      X    0    1    A    B    C
2  1  0.1  0.2  0.3 | 1  NaN  3.0  5.0  NaN  NaN  NaN
3  2  0.1  0.2  0.3 | 2  1.0  4.0  NaN  0.1  0.2  0.3
                    | 3  2.0  NaN  6.0  0.1  0.2  0.3

join

Le troisième argument est join qui décrit si la fusion résultante doit être une fusion externe (par défaut) ou une fusion interne.

rejoindre : {'inner', 'outer'}, par défaut 'outer'.
Comment gérer les index sur d'autres axes.

Il s'avère qu'il n'y a pas left ou right comme pd.concat peut gérer plus que deux objets à fusionner.

Dans le cas de d1 et d2 les options sont les suivantes :

outer

pd.concat([d1, d2], axis=1, join='outer')

     A    B    C    B    C    D
1  NaN  NaN  NaN  0.4  0.5  0.6
2  0.1  0.2  0.3  0.4  0.5  0.6
3  0.1  0.2  0.3  NaN  NaN  NaN

inner

pd.concat([d1, d2], axis=1, join='inner')

     A    B    C    B    C    D
2  0.1  0.2  0.3  0.4  0.5  0.6

join_axes

Le quatrième argument est la chose qui nous permet de faire notre left fusionner et plus encore.

axes_joints Liste des objets de l'index
Index spécifiques à utiliser pour les n - 1 autres axes au lieu d'exécuter la logique de réglage intérieur/extérieur.

Fusion à gauche

pd.concat([d1, d2, d3], axis=1, join_axes=[d1.index])

     A    B    C    B    C    D    A    B    D
2  0.1  0.2  0.3  0.4  0.5  0.6  NaN  NaN  NaN
3  0.1  0.2  0.3  NaN  NaN  NaN  0.7  0.8  0.9

Fusion à droite

pd.concat([d1, d2, d3], axis=1, join_axes=[d3.index])

     A    B    C    B    C    D    A    B    D
1  NaN  NaN  NaN  0.4  0.5  0.6  0.7  0.8  0.9
3  0.1  0.2  0.3  NaN  NaN  NaN  0.7  0.8  0.9

ignore_index

ignore_index : booléen, par défaut False
Si Vrai, ne pas utiliser les valeurs d'index le long de l'axe de concaténation. L'axe résultant sera étiqueté 0, ..., n - 1. Ceci est utile si vous concaténer des objets où l'axe de concaténation ne contient pas d'informations d'indexation significatives. Notez que les valeurs d'indexation des autres axes sont toujours respectées dans la jointure.

Comme quand j'empile d1 sur le dessus de d2 Si je ne me soucie pas des valeurs d'index, je peux les réinitialiser ou les ignorer.

                      |  pd.concat(             |  pd.concat(
                      |      [d1, d2],          |      [d1, d2]
 pd.concat([d1, d2])  |      ignore_index=True) |  ).reset_index(drop=True)
--------------------- | ----------------------- | -------------------------
     A    B    C    D |      A    B    C    D   |      A    B    C    D
2  0.1  0.2  0.3  NaN | 0  0.1  0.2  0.3  NaN   | 0  0.1  0.2  0.3  NaN
3  0.1  0.2  0.3  NaN | 1  0.1  0.2  0.3  NaN   | 1  0.1  0.2  0.3  NaN
1  NaN  0.4  0.5  0.6 | 2  NaN  0.4  0.5  0.6   | 2  NaN  0.4  0.5  0.6
2  NaN  0.4  0.5  0.6 | 3  NaN  0.4  0.5  0.6   | 3  NaN  0.4  0.5  0.6

Et quand on utilise axis=1 :

                                   |     pd.concat(
                                   |         [d1, d2], axis=1,
 pd.concat([d1, d2], axis=1)       |         ignore_index=True)
-------------------------------    |    -------------------------------
     A    B    C    B    C    D    |         0    1    2    3    4    5
1  NaN  NaN  NaN  0.4  0.5  0.6    |    1  NaN  NaN  NaN  0.4  0.5  0.6
2  0.1  0.2  0.3  0.4  0.5  0.6    |    2  0.1  0.2  0.3  0.4  0.5  0.6
3  0.1  0.2  0.3  NaN  NaN  NaN    |    3  0.1  0.2  0.3  NaN  NaN  NaN

keys

Nous pouvons passer une liste de valeurs scalaires ou de tuples afin d'assigner des valeurs scalaires ou de tuple aux MultiIndex correspondants. La longueur de la liste passée doit être la même que le nombre d'éléments à concaténer.

clés : séquence, par défaut None
Si plusieurs niveaux sont passés, ils doivent contenir des tuples. Construit un index hiérarchique en utilisant les clés passées comme niveau le plus éloigné.

axis=0

Lors de la concaténation Series des objets le long de axis=0 (extension de l'index).

Ces clés, deviennent un nouveau niveau initial d'une MultiIndex dans l'attribut index.

 #           length 3             length 3           #         length 2        length 2
 #          /--------\         /-----------\         #          /----\         /------\
 pd.concat([s1, s2, s3], keys=['A', 'B', 'C'])       pd.concat([s1, s2], keys=['A', 'B'])
----------------------------------------------      -------------------------------------
A  2    1                                           A  2    1
   3    2                                              3    2
B  1    3                                           B  1    3
   2    4                                              2    4
C  1    5                                           dtype: int64
   3    6
dtype: int64

Cependant, nous pouvons utiliser plus que des valeurs scalaires dans la fonction keys pour créer un argument encore plus profond MultiIndex . Ici, nous passons tuples de longueur 2, on ajoute deux nouveaux niveaux de a MultiIndex :

 pd.concat(
     [s1, s2, s3],
     keys=[('A', 'X'), ('A', 'Y'), ('B', 'X')])
-----------------------------------------------
A  X  2    1
      3    2
   Y  1    3
      2    4
B  X  1    5
      3    6
dtype: int64

axis=1

C'est un peu différent lorsque l'on s'étend le long des colonnes. Lorsque nous avons utilisé axis=0 (voir ci-dessus) notre keys a agi en tant que MultiIndex en plus de l'indice existant. Pour axis=1 nous faisons référence à un axe qui Series n'ont pas, à savoir le columns attribut.

Variations de deux Series avec axis=1

Remarquez que le fait de nommer le s1 et s2 tant qu'aucune keys sont passés, mais ils sont surchargés si keys sont passés.

               |                       |                        |  pd.concat(
               |  pd.concat(           |  pd.concat(            |      [s1.rename('U'),
 pd.concat(    |      [s1, s2],        |      [s1.rename('U'),  |       s2.rename('V')],
     [s1, s2], |      axis=1,          |       s2.rename('V')], |       axis=1,
     axis=1)   |      keys=['X', 'Y']) |       axis=1)          |       keys=['X', 'Y'])
-------------- | --------------------- | ---------------------- | ----------------------
     0    1    |      X    Y           |      U    V            |      X    Y
1  NaN  3.0    | 1  NaN  3.0           | 1  NaN  3.0            | 1  NaN  3.0
2  1.0  4.0    | 2  1.0  4.0           | 2  1.0  4.0            | 2  1.0  4.0
3  2.0  NaN    | 3  2.0  NaN           | 3  2.0  NaN            | 3  2.0  NaN

MultiIndex avec Series et axis=1

 pd.concat(
     [s1, s2],
     axis=1,
     keys=[('W', 'X'), ('W', 'Y')])
-----------------------------------
     W
     X    Y
1  NaN  3.0
2  1.0  4.0
3  2.0  NaN

Deux DataFrame avec axis=1

Comme pour le axis=0 exemples, keys ajouter des niveaux à un MultiIndex mais cette fois-ci vers l'objet stocké dans le fichier columns attribut.

 pd.concat(                     |  pd.concat(
     [d1, d2],                  |      [d1, d2],
     axis=1,                    |      axis=1,
     keys=['X', 'Y'])           |      keys=[('First', 'X'), ('Second', 'X')])
------------------------------- | --------------------------------------------
     X              Y           |   First           Second
     A    B    C    B    C    D |       X                X
1  NaN  NaN  NaN  0.4  0.5  0.6 |       A    B    C      B    C    D
2  0.1  0.2  0.3  0.4  0.5  0.6 | 1   NaN  NaN  NaN    0.4  0.5  0.6
3  0.1  0.2  0.3  NaN  NaN  NaN | 2   0.1  0.2  0.3    0.4  0.5  0.6
                                | 3   0.1  0.2  0.3    NaN  NaN  NaN

Series et DataFrame avec axis=1

Ceci est délicat. Dans ce cas, une valeur de clé scalaire ne peut pas servir d'unique niveau d'index pour le fichier Series lorsqu'il devient une colonne, tout en faisant office de premier niveau d'un objet MultiIndex pour le DataFrame . Ainsi, les Pandas utiliseront à nouveau le name de l'attribut Series comme source du nom de la colonne.

 pd.concat(           |  pd.concat(
     [s1, d1],        |      [s1.rename('Z'), d1],
     axis=1,          |      axis=1,
     keys=['X', 'Y']) |      keys=['X', 'Y'])
--------------------- | --------------------------
   X    Y             |    X    Y
   0    A    B    C   |    Z    A    B    C
2  1  0.1  0.2  0.3   | 2  1  0.1  0.2  0.3
3  2  0.1  0.2  0.3   | 3  2  0.1  0.2  0.3

Limites de la keys et MultiIndex inférence.

Pandas ne semble déduire les noms de colonnes qu'à partir de Series mais il ne remplira pas les blancs lors d'une concaténation analogue entre des cadres de données ayant un nombre différent de niveaux de colonnes.

d1_ = pd.concat(
    [d1], axis=1,
    keys=['One'])
d1_

   One
     A    B    C
2  0.1  0.2  0.3
3  0.1  0.2  0.3

Ensuite, concaténons-le avec un autre cadre de données avec un seul niveau dans l'objet colonnes et Pandas refusera d'essayer de faire des tuples de l'objet MultiIndex et combine tous les cadres de données comme s'il s'agissait d'un seul niveau d'objets, de scalaires et de tuples.

pd.concat([d1_, d2], axis=1)

   (One, A)  (One, B)  (One, C)    B    C    D
1       NaN       NaN       NaN  0.4  0.5  0.6
2       0.1       0.2       0.3  0.4  0.5  0.6
3       0.1       0.2       0.3  NaN  NaN  NaN

Passage d'un dict au lieu d'un list

Lors du passage d'un dictionnaire, pandas.concat utilisera les clés du dictionnaire en tant qu'objet keys paramètre.

 # axis=0               |  # axis=1
 pd.concat(             |  pd.concat(
     {0: d1, 1: d2})    |      {0: d1, 1: d2}, axis=1)
----------------------- | -------------------------------
       A    B    C    D |      0              1
0 2  0.1  0.2  0.3  NaN |      A    B    C    B    C    D
  3  0.1  0.2  0.3  NaN | 1  NaN  NaN  NaN  0.4  0.5  0.6
1 1  NaN  0.4  0.5  0.6 | 2  0.1  0.2  0.3  0.4  0.5  0.6
  2  NaN  0.4  0.5  0.6 | 3  0.1  0.2  0.3  NaN  NaN  NaN

levels

Il est utilisé en conjonction avec le keys Lorsque levels est laissé à sa valeur par défaut de None Pandas prendra les valeurs uniques de chaque niveau de l'arbre résultant. MultiIndex et l'utiliser comme objet utilisé dans le résultat de l'opération. index.levels attribut.

niveaux : liste de séquences, par défaut None
Niveaux spécifiques (valeurs uniques) à utiliser pour construire un MultiIndex. Sinon, ils seront déduits des clés.

Si Pandas déduit déjà ce que doivent être ces niveaux, quel avantage y a-t-il à les spécifier nous-mêmes ? Je vais vous montrer un exemple et je vous laisse le soin de trouver d'autres raisons pour lesquelles cela pourrait être utile.

Exemple

Selon la documentation, le levels est une liste de séquences. Cela signifie que nous pouvons utiliser une autre pandas.Index comme l'une de ces séquences.

Considérons le cadre de données df qui est la concaténation de d1 , d2 et d3 :

df = pd.concat(
    [d1, d2, d3], axis=1,
    keys=['First', 'Second', 'Fourth'])

df

  First           Second           Fourth
      A    B    C      B    C    D      A    B    D
1   NaN  NaN  NaN    0.4  0.5  0.6    0.7  0.8  0.9
2   0.1  0.2  0.3    0.4  0.5  0.6    NaN  NaN  NaN
3   0.1  0.2  0.3    NaN  NaN  NaN    0.7  0.8  0.9

Les niveaux de l'objet colonnes sont :

print(df, *df.columns.levels, sep='\n')

Index(['First', 'Second', 'Fourth'], dtype='object')
Index(['A', 'B', 'C', 'D'], dtype='object')

Si nous utilisons sum dans un groupby on obtient :

df.groupby(axis=1, level=0).sum()

   First  Fourth  Second
1    0.0     2.4     1.5
2    0.6     0.0     1.5
3    0.6     2.4     0.0

Mais si au lieu de ['First', 'Second', 'Fourth'] il y avait d'autres catégories manquantes nommées Third et Fifth ? Et je voulais qu'ils soient inclus dans les résultats d'un groupby agrégation ? Nous pouvons le faire si nous avions un pandas.CategoricalIndex . Et nous pouvons le spécifier à l'avance avec la fonction levels argument.

Donc, à la place, définissons df comme :

cats = ['First', 'Second', 'Third', 'Fourth', 'Fifth']
lvl = pd.CategoricalIndex(cats, categories=cats, ordered=True)

df = pd.concat(
    [d1, d2, d3], axis=1,
    keys=['First', 'Second', 'Fourth'],
    levels=[lvl]
)

df

   First  Fourth  Second
1    0.0     2.4     1.5
2    0.6     0.0     1.5
3    0.6     2.4     0.0

Mais le premier niveau de l'objet colonnes est :

df.columns.levels[0]

CategoricalIndex(
    ['First', 'Second', 'Third', 'Fourth', 'Fifth'],
    categories=['First', 'Second', 'Third', 'Fourth', 'Fifth'],
    ordered=True, dtype='category')

Et notre groupby ressemble à un résumé :

df.groupby(axis=1, level=0).sum()

   First  Second  Third  Fourth  Fifth
1    0.0     1.5    0.0     2.4    0.0
2    0.6     1.5    0.0     0.0    0.0
3    0.6     0.0    0.0     2.4    0.0

names

Ceci est utilisé pour nommer les niveaux d'un résultat. MultiIndex . La longueur de la names doit correspondre au nombre de niveaux dans la liste résultante MultiIndex .

noms : liste, par défaut None
Noms des niveaux de l'index hiérarchique résultant.

 # axis=0                     |  # axis=1
 pd.concat(                   |  pd.concat(
     [d1, d2],                |      [d1, d2],
     keys=[0, 1],             |      axis=1, keys=[0, 1],
     names=['lvl0', 'lvl1'])  |      names=['lvl0', 'lvl1'])
----------------------------- | ----------------------------------
             A    B    C    D | lvl0    0              1
lvl0 lvl1                     | lvl1    A    B    C    B    C    D
0    2     0.1  0.2  0.3  NaN | 1     NaN  NaN  NaN  0.4  0.5  0.6
     3     0.1  0.2  0.3  NaN | 2     0.1  0.2  0.3  0.4  0.5  0.6
1    1     NaN  0.4  0.5  0.6 | 3     0.1  0.2  0.3  NaN  NaN  NaN
     2     NaN  0.4  0.5  0.6 |

verify_integrity

Documentation auto-explicative

vérifier_intégrité : booléen, par défaut False
Vérifiez si le nouvel axe concaténé contient des doublons. Cela peut être très coûteux par rapport à la concaténation réelle des données.

Parce que l'index résultant de la concaténation d1 et d2 n'est pas unique, il échouerait au contrôle d'intégrité.

pd.concat([d1, d2])

     A    B    C    D
2  0.1  0.2  0.3  NaN
3  0.1  0.2  0.3  NaN
1  NaN  0.4  0.5  0.6
2  NaN  0.4  0.5  0.6

Et

pd.concat([d1, d2], verify_integrity=True)

> ValueError : Les index ont des valeurs qui se chevauchent : [2]

25 votes

Il serait vraiment plus utile pour la communauté de faire simplement une demande de retrait pour ajouter quelques exemples manquants (juste deux) à la documentation principale ; SO est seulement consultable et ne peut pas être parcouru ; mettre un lien vers la documentation serait utile ici - la grande majorité de ceci est déjà bien et complètement documentée

6 votes

@Jeff il y a des dimensions de ma croissance qui ont été lentes. L'utilisation de Git est l'une d'entre elles. Je promets que c'est ce que je veux commencer à faire.

0 votes

Utilisation de pd.concat(..., levels=[lvl]).groupby(axis=1, level=0).sum() produit un résultat différent de pd.concat(..., levels=[cats]).groupby(axis=1, level=0).sum() . Savez-vous pourquoi ? Les docs disent seulement levels doit être une liste de séquences.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X