Qual é a diferença entre ingressar e mesclar no Pandas?

208

Suponha que eu tenha dois DataFrames como este:

left = pd.DataFrame({'key1': ['foo', 'bar'], 'lval': [1, 2]})

right = pd.DataFrame({'key2': ['foo', 'bar'], 'rval': [4, 5]})

Quero mesclá-los, então tento algo assim:

pd.merge(left, right, left_on='key1', right_on='key2')

E eu estou feliz

    key1    lval    key2    rval
0   foo     1       foo     4
1   bar     2       bar     5

Mas estou tentando usar o método join, no qual fui levado a acreditar que é bastante semelhante.

left.join(right, on=['key1', 'key2'])

E eu entendo isso:

//anaconda/lib/python2.7/site-packages/pandas/tools/merge.pyc in _validate_specification(self)
    406             if self.right_index:
    407                 if not ((len(self.left_on) == self.right.index.nlevels)):
--> 408                     raise AssertionError()
    409                 self.right_on = [None] * n
    410         elif self.right_on is not None:

AssertionError: 

o que estou perdendo?

munk
fonte
4
O problema específico aqui é que mergeune colunas de lefta colunas de right, que é o que você deseja, mas join(... on=[...])une colunas de lefta chaves de índice de right, que não é o que você deseja. Veja minha resposta abaixo para mais detalhes.
Matthias Fripp
3
O DataFrame.join () sempre deseja corresponder os índices ou as chaves do chamador (especificados por onopção) com os índices do chamador other. Lembre-se, índices para associação. Enquanto merge () é um método mais genérico.
Jiapeng Zhang 4/03/19

Respostas:

87

Eu sempre uso joinem índices:

import pandas as pd
left = pd.DataFrame({'key': ['foo', 'bar'], 'val': [1, 2]}).set_index('key')
right = pd.DataFrame({'key': ['foo', 'bar'], 'val': [4, 5]}).set_index('key')
left.join(right, lsuffix='_l', rsuffix='_r')

     val_l  val_r
key            
foo      1      4
bar      2      5

A mesma funcionalidade pode ser obtida usando mergeas colunas a seguir:

left = pd.DataFrame({'key': ['foo', 'bar'], 'val': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'bar'], 'val': [4, 5]})
left.merge(right, on=('key'), suffixes=('_l', '_r'))

   key  val_l  val_r
0  foo      1      4
1  bar      2      5
Paul H
fonte
O erro parece estar dizendo que espera que o índice múltiplo righttenha a mesma profundidade que o comprimento on. Isso faz sentido para mim. Eu posso aceitar que a semântica é diferente. Mas eu gostaria de saber se eu posso obter esse mesmo comportamento com df.join
munk
346

pandas.merge() é a função subjacente usada para todo o comportamento de mesclagem / junção.

Os DataFrames fornecem os métodos pandas.DataFrame.merge()e pandas.DataFrame.join()como uma maneira conveniente de acessar os recursos do pandas.merge(). Por exemplo, df1.merge(right=df2, ...)é equivalente a pandas.merge(left=df1, right=df2, ...).

Estas são as principais diferenças entre df.join()e df.merge():

  1. pesquisa na tabela à direita: df1.join(df2)sempre ingressa no índice de df2, mas df1.merge(df2)pode ingressar em uma ou mais colunas de df2(padrão) ou no índice de df2(com right_index=True).
  2. pesquisa na tabela esquerda: por padrão, df1.join(df2)usa o índice de df1e df1.merge(df2)usa a (s) coluna (s) de df1. Isso pode ser substituído especificando df1.join(df2, on=key_or_keys)ou df1.merge(df2, left_index=True).
  3. junção esquerda vs interna: df1.join(df2)faz uma junção esquerda por padrão (mantém todas as linhas de df1), mas df.mergefaz uma junção interna por padrão (retorna apenas as linhas correspondentes de df1e df2).

Portanto, a abordagem genérica é usar pandas.merge(df1, df2)or df1.merge(df2). Porém, em várias situações comuns (mantendo todas as linhas df1e ingressando em um índice df2), você pode salvar algumas digitações usando df1.join(df2).

Algumas notas sobre esses problemas da documentação em http://pandas.pydata.org/pandas-docs/stable/merging.html#database-style-dataframe-joining-merging :

merge é uma função no espaço de nomes do pandas e também está disponível como um método de instância DataFrame, com o DataFrame de chamada sendo implicitamente considerado o objeto esquerdo na junção.

O DataFrame.joinmétodo relacionado , usa mergeinternamente para as associações índice-sobre-índice e índice-sobre-coluna (s), mas ingressa nos índices por padrão, em vez de tentar ingressar em colunas comuns (o comportamento padrão para merge). Se você estiver ingressando no índice, convém usar DataFrame.joinpara economizar algumas digitações.

...

Essas duas chamadas de função são completamente equivalentes:

left.join(right, on=key_or_keys)
pd.merge(left, right, left_on=key_or_keys, right_index=True, how='left', sort=False)
Matthias Fripp
fonte
19
Definitivamente, essa deve ser a resposta aceita! Obrigado pela explicação do thourough #
Yohan Obadia
@ Matthias Fripp, Talvez para os mais experientes seja óbvio, mas também se pode dizer que "a pesquisa na tabela à direita: df1.join (df2) pode ser substituída por df1.join (df2, on = key_or_keys?
spacedustpi
@ spacedustpi, acho que você está dizendo que pode usar on=key_or_keyspara alterar a maneira como as linhas são encontradas na tabela correta. No entanto, esse não é realmente o caso. O onargumento altera a pesquisa na tabela esquerda ( df1) do índice para a (s) coluna (s). No entanto, mesmo com esse argumento, a tabela correta ( df2) será correspondida por meio de seu índice. (Veja o último exemplo acima.)
Matthias Fripp
O Pandas possui vários métodos para lidar com essas situações, entre elas mesclar, juntar, acrescentar, concat, combinar, combinar_primeiro. Dê uma olhada em cada uma delas para ter uma idéia de qual seria a melhor para sua situação
xiaxio 29/03/19
13

Eu acredito que join()é apenas um método de conveniência. Tente em df1.merge(df2)vez disso, o que permite especificar left_one right_on:

In [30]: left.merge(right, left_on="key1", right_on="key2")
Out[30]: 
  key1  lval key2  rval
0  foo     1  foo     4
1  bar     2  bar     5
Noé
fonte
11

A partir desta documentação

O pandas fornece uma única função, mesclar, como o ponto de entrada para todas as operações de junção de banco de dados padrão entre os objetos DataFrame:

merge(left, right, how='inner', on=None, left_on=None, right_on=None,
      left_index=False, right_index=False, sort=True,
      suffixes=('_x', '_y'), copy=True, indicator=False)

E:

DataFrame.joiné um método conveniente para combinar as colunas de dois DataFrames potencialmente indexados de maneira diferente em um único DataFrame de resultado. Aqui está um exemplo muito básico: O alinhamento de dados aqui está nos índices (rótulos de linha). Esse mesmo comportamento pode ser alcançado usando a mesclagem e argumentos adicionais instruindo-o a usar os índices:

result = pd.merge(left, right, left_index=True, right_index=True,
how='outer')
Romain Jouin
fonte
8

Uma das diferenças é que mergeestá criando um novo índice e joinmantendo o índice do lado esquerdo. Pode ter uma grande consequência em suas transformações posteriores se você assumir erroneamente que seu índice não foi alterado merge.

Por exemplo:

import pandas as pd

df1 = pd.DataFrame({'org_index': [101, 102, 103, 104],
                    'date': [201801, 201801, 201802, 201802],
                    'val': [1, 2, 3, 4]}, index=[101, 102, 103, 104])
df1

       date  org_index  val
101  201801        101    1
102  201801        102    2
103  201802        103    3
104  201802        104    4

-

df2 = pd.DataFrame({'date': [201801, 201802], 'dateval': ['A', 'B']}).set_index('date')
df2

       dateval
date          
201801       A
201802       B

-

df1.merge(df2, on='date')

     date  org_index  val dateval
0  201801        101    1       A
1  201801        102    2       A
2  201802        103    3       B
3  201802        104    4       B

-

df1.join(df2, on='date')
       date  org_index  val dateval
101  201801        101    1       A
102  201801        102    2       A
103  201802        103    3       B
104  201802        104    4       B
steco
fonte
Está correto. Se mesclarmos os dois quadros de dados em colunas que não sejam índices, obteremos um novo índice, mas se mesclarmos nos índices dos dois quadros de dados, obteremos o quadro de dados com o mesmo índice. Portanto, para obter o mesmo índice após a mesclagem, podemos tornar as colunas nosso índice (nas quais queremos mesclar) para os dois quadros de dados e depois mesclar os quadros de dados no índice recém-criado.
Hasan najeeb
Muito perspicaz. Nunca precisei da indexação (normalmente apenas redefini-la), mas isso pode fazer uma grande diferença em alguns casos.
irene
4
  • Join: Default Index (Se houver o mesmo nome de coluna, ocorrerá um erro no modo padrão porque você não definiu lsuffix ou rsuffix))
df_1.join(df_2)
  • Mesclar: nomes das mesmas colunas padrão (se não houver o mesmo nome de coluna, ocorrerá um erro no modo padrão)
df_1.merge(df_2)
  • on parâmetro tem um significado diferente nos dois casos
df_1.merge(df_2, on='column_1')

df_1.join(df_2, on='column_1') // It will throw error
df_1.join(df_2.set_index('column_1'), on='column_1')
Harsh
fonte
2

Em termos análogos ao SQL "a mesclagem do Pandas é a junção externa / interna e a junção do Pandas é a junção natural". Portanto, quando você usa a mesclagem no pandas, deseja especificar que tipo de junção sqlish deseja usar, enquanto que ao usar a junção pandas, você realmente deseja ter um rótulo de coluna correspondente para garantir que ela se junte

Kaustubh J
fonte