Quais são os 'níveis', 'chaves' e argumentos de nomes para a função concat do Pandas?

94

Questões

  • Como faço para usar pd.concat?
  • Qual é o levelsargumento para?
  • Qual é o keysargumento para?
  • Existem vários exemplos para ajudar a explicar como usar todos os argumentos?

A concatfunção do Pandas é o canivete suíço dos utilitários em fusão. A variedade de situações em que é útil é numerosa. A documentação existente omite alguns detalhes sobre alguns dos argumentos opcionais. Entre eles estão os argumentos levelse keys. Eu comecei a descobrir o que esses argumentos fazem.

Vou fazer uma pergunta que funcionará como um portal para muitos aspectos do pd.concat.

Considere os quadros de dados 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 eu fosse concatená-los junto com

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

Eu obtenho o resultado esperado com um pandas.MultiIndexpara meu columnsobjeto:

        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

No entanto, eu queria usar a levelsdocumentação do argumento :

níveis : lista de sequências, padrão Nenhum. Níveis específicos (valores únicos) a serem usados ​​para construir um MultiIndex. Caso contrário, eles serão inferidos das chaves.

Então eu passei

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

E obter um KeyError

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

Isso fazia sentido. Os níveis pelos quais passei eram inadequados para descrever os níveis necessários indicados pelas teclas. Se eu não tivesse passado em nada, como fiz acima, os níveis são inferidos (conforme consta na documentação). Mas de que outra forma posso usar esse argumento para obter um efeito melhor?

Se eu tentasse isso:

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

I e obtivemos os mesmos resultados acima. Mas quando adiciono mais um valor aos níveis,

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

Acabo com o mesmo quadro de dados de aparência, mas o resultado MultiIndextem um nível não utilizado.

df.index.levels[0]

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

Então, qual é o objetivo do levelargumento e devo usá-lo de forma keysdiferente?

Estou usando Python 3.6 e Pandas 0.22.

piRSquared
fonte

Respostas:

123

No processo de responder a essa pergunta para mim mesmo, aprendi muitas coisas e queria montar um catálogo de exemplos e algumas explicações.

A resposta específica para o ponto do levelsargumento virá no final.

pandas.concat: The Missing Manual

Link para a documentação atual

Importação e definição de objetos

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

Argumentos

objs

O primeiro argumento que encontramos é objs:

objs : uma sequência ou mapeamento de objetos Series, DataFrame ou Panel Se um dict for passado, as chaves classificadas serão usadas como o argumento keys, a menos que seja passado, caso em que os valores serão selecionados (veja abaixo). Qualquer objeto None será descartado silenciosamente a menos que sejam todos None, caso em que um ValueError será gerado

  • Normalmente vemos isso usado com uma lista de objetos Seriesou DataFrame.
  • Vou mostrar que também dictpode ser muito útil.
  • Geradores também podem ser usados ​​e podem ser úteis quando usados mapcomo emmap(f, list_of_df)

Por enquanto, ficaremos com uma lista de alguns dos objetos DataFramee Seriesdefinidos acima. Mostrarei como os dicionários podem ser aproveitados para fornecer MultiIndexresultados muito úteis posteriormente.

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

O segundo argumento que encontramos é axiscujo valor padrão é 0:

eixo : {0 / 'índice', 1 / 'colunas'}, padrão 0 O eixo ao longo do qual concatenar.

Dois DataFrames com axis=0(empilhados)

Para valores de 0ou indexqueremos dizer: "Alinhe ao longo das colunas e adicione ao índice".

Conforme mostrado acima, onde usamos axis=0, porque 0é o valor padrão, e vemos que o índice de d2estende o índice de d1apesar de haver sobreposição do valor 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

Dois DataFrames com axis=1(lado a lado)

Para valores 1ou columnsqueremos dizer: "Alinhe ao longo do índice e adicione às colunas",

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

Podemos ver que o índice resultante é a união dos índices e as colunas resultantes são a extensão das colunas de d1pelas colunas de d2.

Dois (ou três) Seriescom axis=0(empilhados)

Ao combinar pandas.Seriesjunto axis=0, obtemos a pandas.Series. O nome do resultado Seriesserá a Nonemenos que todos Seriessendo combinados tenham o mesmo nome. Preste atenção ao 'Name: A'quando imprimirmos o resultado Series. Quando não está presente, podemos assumir que o Seriesnome 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

Dois (ou três) Seriescom axis=1(lado a lado)

Ao combinar pandas.Seriesjunto axis=1, é o nameatributo ao qual nos referimos para inferir um nome de coluna no resultado 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

Misturado Seriese DataFramecom axis=0(empilhado)

Ao realizar uma concatenação de a Seriese DataFramealong axis=0, convertemos todos Seriesem uma única coluna DataFrames.

Observe que esta é uma concatenação junto axis=0; isso significa estender o índice (linhas) enquanto alinha as colunas. Nos exemplos abaixo, vemos que o índice se torna, [2, 3, 2, 3]que é um acréscimo indiscriminado de índices. As colunas não se sobrepõem, a menos que eu force a nomenclatura da Seriescoluna com o argumento para 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

Você pode ver que os resultados pd.concat([s1, d1])são os mesmos como se eu tivesse executado a to_framemim mesmo.

No entanto, posso controlar o nome da coluna resultante com um parâmetro para to_frame. Renomear o Seriescom o renamemétodo não controla o nome da coluna no resultado 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

Misturado Seriese DataFramecom axis=1(lado a lado)

Isso é bastante intuitivo. SeriesO nome da coluna é padronizado para uma enumeração de tais Seriesobjetos quando um nameatributo não está disponível.

                    |  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

O terceiro argumento é joinque descreve se a mesclagem resultante deve ser uma mesclagem externa (padrão) ou uma mesclagem interna.

join : {'interno', 'externo'}, padrão 'externo'
Como lidar com índices em outro (s) eixo (s).

Acontece que não há nenhuma opção leftou rightque pd.concatpossa lidar com mais do que apenas dois objetos para mesclar.

No caso de d1e d2, as opções são semelhantes a:

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

O quarto argumento é o que nos permite fazer nossa leftfusão e muito mais.

join_axes : lista de objetos Index
Índices específicos a serem usados ​​para os outros n - 1 eixos em vez de realizar a lógica de conjunto interno / externo.

Esquerda Unir

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

Unir à direita

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, não use os valores de índice ao longo do eixo de concatenação. O eixo resultante será rotulado 0, ..., n - 1. Isso é útil se você estiver concatenando objetos onde o eixo de concatenação não tem informações de indexação significativas. Observe que os valores de índice nos outros eixos ainda são respeitados na junção.

Como quando eu empilhar d1em cima do d2, se eu não me importar com os valores do índice, posso redefini-los ou ignorá-los.

                      |  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 ao usar 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

Podemos passar uma lista de valores escalares ou tuplas para atribuir tupla ou valores escalares ao MultiIndex correspondente. O comprimento da lista passada deve ser igual ao número de itens sendo concatenados.

keys : sequence, default None
Se vários níveis forem passados, deve conter tuplas. Construa um índice hierárquico usando as chaves passadas como o nível mais externo

axis=0

Ao concatenar Seriesobjetos ao longo axis=0(estendendo o índice).

Essas chaves se tornam um novo nível inicial de um MultiIndexobjeto no atributo de índice.

 #           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

No entanto, podemos usar mais do que valores escalares no keysargumento para criar um ainda mais profundo MultiIndex. Aqui, passamos tuplesdo comprimento 2 antes de dois novos níveis de um 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

É um pouco diferente quando se estende ao longo de colunas. Quando usamos axis=0(veja acima) nossos níveis keysagiram como MultiIndexadicionais ao índice existente. Pois axis=1, estamos nos referindo a um eixo que os Seriesobjetos não têm, ou seja, o columnsatributo.

Variações de dois Seriescomaxis=1

Observe que nomear o s1e é s2importante, desde que não keysseja passado, mas será substituído se keysfor aprovado.

               |                       |                        |  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
MultiIndexcom 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
Dois DataFramecomaxis=1

Como nos axis=0exemplos, keysadicione níveis a a MultiIndex, mas desta vez ao objeto armazenado no columnsatributo.

 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 DataFramecomaxis=1

Isso é complicado. Nesse caso, um valor de chave escalar não pode atuar como o único nível de índice para o Seriesobjeto quando ele se torna uma coluna, ao mesmo tempo que atua como o primeiro nível de a MultiIndexpara o DataFrame. Portanto, o Pandas usará novamente o nameatributo do Seriesobjeto como a origem do nome da coluna.

 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
Limitações keyse MultiIndexinferências.

O Pandas parece apenas inferir nomes de colunas a partir do Seriesnome, mas não preencherá os espaços em branco ao fazer uma concatenação análoga entre quadros de dados com um número diferente de níveis de coluna.

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

Em seguida, concatene isso com outro quadro de dados com apenas um nível no objeto colunas e Pandas se recusará a tentar fazer tuplas do MultiIndexobjeto e combinar todos os quadros de dados como se fosse um único nível de objetos, escalares e tuplas.

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 por um em dictvez de umlist

Ao passar um dicionário, pandas.concatusará as chaves do dicionário como keysparâmetro.

 # 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

Isso é usado em conjunto com o keysargumento. Quando levelsfor deixado como seu valor padrão de None, o Pandas pegará os valores exclusivos de cada nível do resultante MultiIndexe os usará como o objeto usado no index.levelsatributo resultante .

níveis : lista de sequências, padrão Nenhum
Níveis específicos (valores exclusivos) para usar para construir um MultiIndex. Caso contrário, eles serão inferidos das chaves.

Se o Pandas já infere quais deveriam ser esses níveis, qual a vantagem de especificá-los nós mesmos? Vou mostrar um exemplo e deixar para você pensar em outras razões pelas quais isso pode ser útil.

Exemplo

De acordo com a documentação, o levelsargumento é uma lista de sequências. Isso significa que podemos usar outro pandas.Indexcomo uma dessas sequências.

Considere o quadro de dados dfque é a concatenação de 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

Os níveis do objeto colunas são:

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

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

Se usarmos sumem um groupby, obtemos:

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

Mas e se, em vez de, ['First', 'Second', 'Fourth']houvesse outra categoria ausente chamada Thirde Fifth? E eu queria que eles fossem incluídos nos resultados de uma groupbyagregação? Podemos fazer isso se tivermos um pandas.CategoricalIndex. E podemos especificar isso com antecedência com o levelsargumento.

Então, em vez disso, vamos definir dfcomo:

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

Mas o primeiro nível do objeto de colunas é:

df.columns.levels[0]

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

E nosso groupbyresumo se parece com:

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

Isso é usado para nomear os níveis de um resultante MultiIndex. O comprimento da nameslista deve corresponder ao número de níveis no resultado MultiIndex.

nomes : lista, padrão Nenhum
Nomes para os níveis no índice hierárquico resultante

 # 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

Documentação autoexplicativa

verify_integrity : boolean, default False
Verifique se o novo eixo concatenado contém duplicatas. Isso pode ser muito caro em relação à concatenação de dados real.

Como o índice resultante da concatenação d1e d2não é exclusivo, ele falhará na verificação de integridade.

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: os índices têm valores sobrepostos: [2]

piRSquared
fonte
23
realmente seria muito mais útil para a comunidade simplesmente fazer uma solicitação pull para adicionar alguns exemplos ausentes (apenas alguns) aos documentos principais; SO é apenas pesquisável e não navegável; além disso, colocar um link para os documentos seria útil aqui - a grande maioria disso já está bem e completamente documentado
Jeff,
6
@Jeff, algumas dimensões do meu crescimento têm sido lentas. Usar o git é um deles. Prometo que é isso que quero começar a fazer.
piRSquared
Usar pd.concat(..., levels=[lvl]).groupby(axis=1, level=0).sum()produz um resultado diferente de pd.concat(..., levels=[cats]).groupby(axis=1, level=0).sum(). Você sabe por quê? Os documentos dizem apenas que levelsdeve haver uma lista de sequências.
unutbu
1
Ótima resposta, mas acho que a seção sobre Passing a dict instead of a listprecisa de um exemplo usando um dicionário, não uma lista.
unutbu
1
@unutbu Corrigi o dictexemplo, thx. A razão é que lvlé um índice categórico e catsé apenas uma lista. Ao agrupar por um tipo categórico, as categorias ausentes são preenchidas com zeros e nulos quando apropriado. Veja isto
piRSquared