Quali sono gli argomenti "livelli", "chiavi" e nomi nella funzione concatenata di Pandas?


94

Domande

  • Come si usa pd.concat?
  • Qual è l' levelsargomento per?
  • Qual è l' keysargomento per?
  • Ci sono un sacco di esempi per aiutare a spiegare come utilizzare tutti gli argomenti?

La concatfunzione di Pandas è il coltellino svizzero dei servizi di fusione. Le varietà di situazioni in cui è utile sono numerose. La documentazione esistente tralascia alcuni dettagli su alcuni degli argomenti opzionali. Tra questi ci sono gli argomenti levelse keys. Ho deciso di capire cosa fanno questi argomenti.

Porrò una domanda che fungerà da gateway in molti aspetti di pd.concat.

Considerare i frame di dati d1, d2e 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])

Se dovessi concatenarli insieme a

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

Ottengo il risultato atteso con un pandas.MultiIndexper il mio columnsoggetto:

        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

Tuttavia, ho voluto utilizzare la levelsdocumentazione dell'argomento :

livelli : elenco di sequenze, predefinito Nessuno. Livelli specifici (valori univoci) da utilizzare per costruire un MultiIndex. In caso contrario, verranno dedotti dalle chiavi.

Così sono passato

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

E ottieni un file KeyError

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

Questo aveva senso. I livelli che ho superato erano inadeguati a descrivere i livelli necessari indicati dai tasti. Se non avessi superato nulla, come ho fatto sopra, i livelli vengono desunti (come indicato nella documentazione). Ma in quale altro modo posso utilizzare questo argomento per ottenere risultati migliori?

Se invece ho provato questo:

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

Ho ottenuto gli stessi risultati di cui sopra. Ma quando aggiungo un valore in più ai livelli,

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

Finisco con lo stesso frame di dati dall'aspetto, ma il risultato MultiIndexha un livello inutilizzato.

df.index.levels[0]

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

Allora qual è il punto leveldell'argomento e dovrei usare in modo keysdiverso?

Sto usando Python 3.6 e Pandas 0.22.

Risposte:


123

Mentre rispondevo personalmente a questa domanda, ho imparato molte cose e volevo mettere insieme un catalogo di esempi e alcune spiegazioni.

La risposta specifica al punto levelsdell'argomento arriverà verso la fine.

pandas.concat: Il manuale mancante

Collegamento alla documentazione corrente

Importazioni e definizione di oggetti

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])

argomenti

objs

Il primo argomento che incontriamo è objs:

objs : una sequenza o mappatura di oggetti Series, DataFrame o Panel Se viene passato un dict, le chiavi ordinate verranno utilizzate come argomento delle chiavi, a meno che non vengano passate, nel qual caso verranno selezionati i valori (vedere di seguito). Tutti gli oggetti None verranno rilasciati silenziosamente a meno che non siano tutti None, nel qual caso verrà sollevata un'eccezione ValueError

  • In genere lo vediamo usato con un elenco di Serieso DataFrameoggetti.
  • Mostrerò anche che dictpuò essere molto utile.
  • Possono essere usati anche generatori e possono essere utili quando si usa mapcome inmap(f, list_of_df)

Per ora, ci limiteremo a un elenco di alcuni degli oggetti DataFramee Seriesdefiniti sopra. Mostrerò in seguito come utilizzare i dizionari per fornire MultiIndexrisultati molto utili .

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

Il secondo argomento che incontriamo è il axiscui valore predefinito è 0:

asse : {0 / 'indice', 1 / 'colonne'}, valore predefinito 0 L'asse da concatenare.

Due DataFrames con axis=0(sovrapposti)

Per valori di 0o indexintendiamo dire: "Allinea lungo le colonne e aggiungi all'indice".

Come mostrato sopra, dove abbiamo usato axis=0, perché 0è il valore predefinito, e vediamo che l'indice di d2estende l'indice di d1nonostante ci sia una sovrapposizione del valore 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

Due DataFrames con axis=1(fianco a fianco)

Per i valori 1o columnsintendiamo dire: "Allinea lungo l'indice e aggiungi alle colonne",

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

Possiamo vedere che l'indice risultante è l'unione di indici e le colonne risultanti sono l'estensione delle colonne dalle d1colonne di d2.

Due (o tre) Seriescon axis=0(impilati)

Quando si combinano pandas.Seriesinsieme axis=0, torniamo a pandas.Series. Il nome del risultato Seriessarà a Nonemeno che tutti quelli Seriescombinati non abbiano lo stesso nome. Presta attenzione a 'Name: A'quando stampiamo il risultato Series. Quando non è presente, possiamo presumere che il Seriesnome lo sia 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

Due (o Tre) Seriescon axis=1(fianco a fianco)

Quando si combinano pandas.Seriesinsieme axis=1, è l' nameattributo a cui ci riferiamo per dedurre un nome di colonna nel file risultante 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

Misto Seriese DataFramecon axis=0(impilato)

Quando si esegue una concatenazione di a Seriese DataFramelungo axis=0, convertiamo tutto Seriesin una singola colonna DataFrames.

Tieni presente che questa è una concatenazione lungo axis=0; ciò significa estendere l'indice (righe) mentre si allineano le colonne. Negli esempi seguenti, vediamo l'indice [2, 3, 2, 3]che diventa un'aggiunta indiscriminata di indici. Le colonne non si sovrappongono a meno che non forzi la denominazione della Seriescolonna con l'argomento a 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

Puoi vedere i risultati di pd.concat([s1, d1])sono gli stessi come se avessi ottenuto il to_frameme stesso.

Tuttavia, posso controllare il nome della colonna risultante con un parametro a to_frame. Rinominare Seriescon il renamemetodo non controlla il nome della colonna nel file risultante 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

Misto Seriese DataFramecon axis=1(fianco a fianco)

Questo è abbastanza intuitivo. Seriesil nome della colonna utilizza per impostazione predefinita un'enumerazione di tali Seriesoggetti quando un nameattributo non è disponibile.

                    |  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

Il terzo argomento è joinche descrive se l'unione risultante deve essere un'unione esterna (impostazione predefinita) o un'unione interna.

join : {'inner', 'outer'}, default 'outer'
Come gestire gli indici su altri assi.

Si scopre che non esiste un'opzione lefto in rightquanto pd.concatpuò gestire più di due oggetti da unire.

Nel caso di d1e d2, le opzioni sono:

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

Il quarto argomento è la cosa che ci permette di fare la nostra leftfusione e altro ancora.

join_axes : elenco di oggetti Index
Indici specifici da utilizzare per gli altri n - 1 assi invece di eseguire la logica degli insiemi interno / esterno.

Unisci a sinistra

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

Unione a destra

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 : boolean, default False
Se True, non utilizzare i valori di indice lungo l'asse di concatenazione. L'asse risultante sarà etichettato 0, ..., n - 1. Ciò è utile se si stanno concatenando oggetti in cui l'asse di concatenazione non ha informazioni di indicizzazione significative. Notare che i valori di indice sugli altri assi sono ancora rispettati nel join.

Come quando ho impilare d1in cima d2, se non mi preoccupo per i valori di indice, li avrei potuto reimpostare o ignorarli.

                      |  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

E quando si utilizza 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

Possiamo passare un elenco di valori scalari o tuple per assegnare valori tuple o scalari al MultiIndex corrispondente. La lunghezza dell'elenco passato deve essere uguale al numero di elementi da concatenare.

keys : sequence, default None
Se vengono passati più livelli, dovrebbe contenere tuple. Costruisci un indice gerarchico utilizzando le chiavi passate come livello più esterno

axis=0

Quando si concatenano Seriesoggetti lungo axis=0(estensione dell'indice).

Quelle chiavi diventano un nuovo livello iniziale di un MultiIndexoggetto nell'attributo 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

Tuttavia, possiamo usare più di valori scalari keysnell'argomento per creare un valore ancora più profondo MultiIndex. Qui passiamo tuplesdi lunghezza 2 anteponendo due nuovi livelli di 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

È un po 'diverso quando si estende lungo le colonne. Quando abbiamo usato axis=0(vedi sopra) il nostro ha keysagito come MultiIndexlivelli in aggiunta all'indice esistente. Per axis=1, ci riferiamo a un asse che gli Seriesoggetti non hanno, vale a dire l' columnsattributo.

Variazioni di due Serieswtihaxis=1

Si noti che denominare s1e è s2importante finché non keysviene passato no , ma viene sovrascritto se keysvengono passati.

               |                       |                        |  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
MultiIndexcon Serieseaxis=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
Due DataFrameconaxis=1

Come con gli axis=0esempi, keysaggiungi i livelli a MultiIndex, ma questa volta all'oggetto memorizzato columnsnell'attributo.

 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
Seriese DataFrameconaxis=1

Questo è complicato. In questo caso, un valore chiave scalare non può fungere da unico livello di indice per l' Seriesoggetto quando diventa una colonna mentre agisce anche come primo livello di a MultiIndexper DataFrame. Quindi Panda utilizzerà nuovamente l' nameattributo Seriesdell'oggetto come origine del nome della colonna.

 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
Limitazioni keyse MultiIndexinferrenza.

Panda sembra solo dedurre i nomi delle colonne dal Seriesnome, ma non riempirà gli spazi vuoti quando si esegue una concatenazione analoga tra frame di dati con un numero diverso di livelli di colonna.

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

Quindi concatenalo con un altro frame di dati con un solo livello nell'oggetto colonne e Panda si rifiuterà di provare a creare tuple MultiIndexdell'oggetto e combinare tutti i frame di dati come se fosse un unico livello di oggetti, scalari e tuple.

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

Passando un dictinvece di unlist

Quando si passa un dizionario, pandas.concatutilizzerà le chiavi del dizionario come keysparametro.

 # 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

Viene utilizzato insieme keysall'argomento. Quando levelsviene lasciato come valore predefinito di None, Pandas prenderà i valori univoci di ogni livello del risultato MultiIndexe li utilizzerà come oggetto utilizzato nell'attributo risultante index.levels.

livelli : elenco di sequenze, predefinito Nessuno
Livelli specifici (valori univoci) da utilizzare per costruire un MultiIndex. Altrimenti verranno dedotti dalle chiavi.

Se i Panda già deducono quali dovrebbero essere questi livelli, che vantaggio c'è a specificarlo noi stessi? Mostrerò un esempio e lascio a te pensare ad altri motivi per cui questo potrebbe essere utile.

Esempio

Secondo la documentazione, l' levelsargomento è un elenco di sequenze. Ciò significa che possiamo usarne un altro pandas.Indexcome una di quelle sequenze.

Si consideri il frame di dati dfche è la concatenazione di d1, d2e 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

I livelli dell'oggetto colonne sono:

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

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

Se usiamo sumall'interno di un groupbyotteniamo:

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

Ma cosa succede se al posto di ['First', 'Second', 'Fourth']altre categorie mancanti denominate Thirde Fifth? E li volevo inclusi nei risultati di groupbyun'aggregazione? Possiamo farlo se avessimo un file pandas.CategoricalIndex. E possiamo specificarlo in anticipo con l' levelsargomento.

Quindi, invece, definiamo dfcome:

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

Ma il primo livello dell'oggetto delle colonne è:

df.columns.levels[0]

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

E la nostra groupbysintesi si presenta come:

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

Viene utilizzato per denominare i livelli di un risultato MultiIndex. La lunghezza namesdell'elenco deve corrispondere al numero di livelli nel risultato MultiIndex.

nomi : elenco, predefinito Nessuno
Nomi per i livelli nell'indice gerarchico risultante

 # 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

Documentazione autoesplicativa

verifica_integrità : booleano, valore predefinito False
Controlla se il nuovo asse concatenato contiene duplicati. Questo può essere molto costoso rispetto all'effettiva concatenazione dei dati.

Poiché l'indice risultante dalla concatenazione d1e d2non è univoco, non supererebbe il controllo di integrità.

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

E

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

> ValueError: gli indici hanno valori sovrapposti: [2]


23
sarebbe davvero molto più utile per la comunità fare semplicemente una richiesta pull per aggiungere alcuni esempi mancanti (solo un paio) ai documenti principali; SO è solo ricercabile e non navigabile; sarebbe utile inserire ulteriormente un collegamento ai documenti - la stragrande maggioranza di questo è già ben e completamente documentata
Jeff

6
@ Jeff ci sono dimensioni della mia crescita che sono state lente. Usare git è uno di questi. Prometto che è quello che voglio iniziare a fare.
piRSquared

L'utilizzo pd.concat(..., levels=[lvl]).groupby(axis=1, level=0).sum()produce un risultato diverso da pd.concat(..., levels=[cats]).groupby(axis=1, level=0).sum(). Sai perché? I documenti dicono solo che levelsdovrebbe essere un elenco di sequenze.
unutbu

1
Ottima risposta, ma penso che la sezione su Passing a dict instead of a listnecessiti di un esempio utilizzando un dict, non un elenco.
unutbu

1
@unutbu Ho corretto l' dictesempio, grazie. Il motivo è che lvlè un indice categoriale ed catsè solo un elenco. Quando si raggruppa in base a un tipo categoriale, le categorie mancanti vengono riempite con zeri e valori nulli dove appropriato. Vedi questo
piRSquared
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.