Pular para o conteúdo principal

Tutorial de junção de DataFrames no pandas

Neste tutorial, você aprenderá várias maneiras pelas quais vários DataFrames podem ser mesclados em python usando a biblioteca Pandas.
24 de abr. de 2024  · 19 min de leitura

Você já tentou resolver um desafio da Kaggle? Se sim, você deve ter notado que, na maioria dos desafios, os dados fornecidos a você estão presentes em vários arquivos, com algumas das colunas presentes em mais de um dos arquivos. Bem, qual é a primeira coisa que vem à sua mente? Junte-se a eles, é claro!

Neste tutorial, você praticará algumas técnicas padrão de união de pandas. Mais especificamente, você aprenderá a:

  • Concatenar DataFrames ao longo da linha e da coluna.
  • Mesclar DataFrames em chaves específicas por meio de diferentes lógicas de junção, como junção à esquerda, junção interna, etc.
  • Unir DataFrames por índice.
  • Mesclagem amigável de séries temporais fornecida no pandas

Ao longo do caminho, você também aprenderá alguns truques necessários antes e depois da adesão.

Entrada de pandas

Unir e mesclar DataFrames é o processo principal para iniciar a análise de dados e as tarefas de aprendizado de máquina. É um dos kits de ferramentas que todo analista de dados ou cientista de dados deve dominar porque, em quase todos os casos, os dados vêm de várias fontes e arquivos. Talvez seja necessário reunir todos os dados em um só lugar por meio de algum tipo de lógica de união e, em seguida, iniciar a análise. As pessoas que trabalham com linguagens de consulta do tipo SQL talvez saibam da importância dessa tarefa. Mesmo que você queira criar alguns modelos de aprendizado de máquina em alguns dados, talvez seja necessário mesclar vários arquivos csv em um único DataFrame.

Felizmente, você tem a biblioteca mais popular em python, a pandas, para ajudá-lo! A pandas oferece vários recursos para combinar facilmente objetos Series, DataFrames e Panel com vários tipos de lógica de conjunto para os índices e a funcionalidade de álgebra relacional no caso de operações do tipo união/fusão.

Execute e edite o código deste tutorial online

Executar código

pandas Concatenate

Comece importando a biblioteca que você usará ao longo do tutorial: pandas

import pandas as pd

Você executará todas as operações deste tutorial nos DataFrames fictícios que criará. Para criar um DataFrame, você pode usar um dicionário Python como:

dummy_data1 = {
        'id': ['1', '2', '3', '4', '5'],
        'Feature1': ['A', 'C', 'E', 'G', 'I'],
        'Feature2': ['B', 'D', 'F', 'H', 'J']}

Aqui, as chaves do dicionário dummy_data1 são os nomes das colunas, e os valores da lista são os dados correspondentes a cada observação ou linha. Para transformar isso em um DataFrame do pandas, você usará a função DataFrame() do pandas, juntamente com seu argumento columns para nomear suas colunas:

df1 = pd.DataFrame(dummy_data1, columns = ['id', 'Feature1', 'Feature2'])

df1
  id Recurso1 Feature2
0 1 A B
1 2 C D
2 3 E F
3 4 G H
4 5 I J

Como você pode notar, agora você tem um DataFrame com três colunas id, Feature1 e Feature2. Há uma coluna adicional não nomeada que o pandas cria intrinsecamente como rótulos de linha. Da mesma forma que o DataFrame df1 anterior, você criará mais dois DataFrames df2 e df3:

dummy_data2 = {
        'id': ['1', '2', '6', '7', '8'],
        'Feature1': ['K', 'M', 'O', 'Q', 'S'],
        'Feature2': ['L', 'N', 'P', 'R', 'T']}
df2 = pd.DataFrame(dummy_data2, columns = ['id', 'Feature1', 'Feature2'])

df2
  id Recurso1 Feature2
0 1 K L
1 2 M N
2 6 O P
3 7 Q R
4 8 S T
dummy_data3 = {
        'id': ['1', '2', '3', '4', '5', '7', '8', '9', '10', '11'],
        'Feature3': [12, 13, 14, 15, 16, 17, 15, 12, 13, 23]}
df3 = pd.DataFrame(dummy_data3, columns = ['id', 'Feature3'])

df3
  id Feature3
0 1 12
1 2 13
2 3 14
3 4 15
4 5 16
5 7 17
6 8 15
7 9 12
8 10 13
9 11 23

 concat()

Para simplesmente concatenar os DataFrames ao longo da linha, você pode usar a função concat() no pandas. Você terá de passar os nomes dos DataFrames em uma lista como argumento para a função concat():

df_row = pd.concat([df1, df2])

df_row
  id Recurso1 Feature2
0 1 A B
1 2 C D
2 3 E F
3 4 G H
4 5 I J
0 1 K L
1 2 M N
2 6 O P
3 7 Q R
4 8 S T

Você pode notar que os dois DataFrames df1 e df2 estão agora concatenados em um único DataFrame df_row ao longo da linha. No entanto, os rótulos das linhas parecem estar errados. Se quiser que os rótulos de linha se ajustem automaticamente de acordo com a união, você terá de definir o argumento ignore_index como True ao chamar a função concat():

df_row_reindex = pd.concat([df1, df2], ignore_index=True)

df_row_reindex
  id Recurso1 Feature2
0 1 A B
1 2 C D
2 3 E F
3 4 G H
4 5 I J
5 1 K L
6 2 M N
7 6 O P
8 7 Q R
9 8 S T

Agora os rótulos das linhas estão corretos!

O pandas também oferece uma opção para rotular os DataFrames, após a concatenação, com uma chave para que você possa saber quais dados vieram de qual DataFrame. É possível fazer o mesmo passando chaves de argumentos adicionais que especificam os nomes dos rótulos dos DataFrames em uma lista. Aqui você executará a mesma concatenação com chaves como x e y para DataFrames df1 e df2, respectivamente.

frames = [df1,df2]
df_keys = pd.concat(frames, keys=['x', 'y'])

df_keys
    id Recurso1 Feature2
x 0 1 A B
1 2 C D
2 3 E F
3 4 G H
4 5 I J
y 0 1 K L
1 2 M N
2 6 O P
3 7 Q R
4 8 S T

A menção das chaves também facilita a recuperação de dados correspondentes a um DataFrame específico. Você pode recuperar os dados do DataFrame df2 que tinha o rótulo y usando o método loc:

df_keys.loc['y']
  id Recurso1 Feature2
0 1 K L
1 2 M N
2 6 O P
3 7 Q R
4 8 S T

Você também pode passar um dicionário para concat(), caso em que as chaves do dicionário serão usadas para o argumento keys (a menos que outras chaves sejam especificadas):

pieces = {'x': df1, 'y': df2}

df_piece = pd.concat(pieces)

df_piece
    id Recurso1 Feature2
x 0 1 A B
1 2 C D
2 3 E F
3 4 G H
4 5 I J
y 0 1 K L
1 2 M N
2 6 O P
3 7 Q R
4 8 S T

É importante observar que concat() faz uma cópia completa dos dados, e a reutilização contínua dessa função pode gerar um impacto significativo no desempenho. Se você precisar usar a operação em vários conjuntos de dados, use uma compreensão de lista.

frames = [ process_your_file(f) for f in files ]
result = pd.concat(frames)

Para concatenar DataFrames ao longo da coluna, você pode especificar o parâmetro de eixo como 1 :

df_col = pd.concat([df1,df2], axis=1)

df_col
  id Recurso1 Feature2 id Recurso1 Feature2
0 1 A B 1 K L
1 2 C D 2 M N
2 3 E F 6 O P
3 4 G H 7 Q R
4 5 I J 8 S T

pandas Merge DataFrames

Outra operação onipresente relacionada aos DataFrames é a operação de fusão. Dois DataFrames podem conter diferentes tipos de informações sobre a mesma entidade e estar vinculados por algum recurso/coluna em comum. Para unir esses DataFrames, o pandas fornece várias funções como concat(), merge() , join() etc. Nesta seção, você praticará o uso da função merge() do pandas.

Você pode unir os DataFrames df_row (que você criou concatenando df1 e df2 ao longo da linha) e df3 na coluna (ou chave) comum id. Para fazer isso, passe os nomes dos DataFrames e um argumento adicional como o nome da coluna comum, aqui id, para a função merge():

df_merge_col = pd.merge(df_row, df3, on='id')

df_merge_col
  id Recurso1 Feature2 Feature3
0 1 A B 12
1 1 K L 12
2 2 C D 13
3 2 M N 13
4 3 E F 14
5 4 G H 15
6 5 I J 16
7 7 Q R 17
8 8 S T 15

Você pode notar que os DataFrames agora estão mesclados em um único DataFrame com base nos valores comuns presentes na coluna id de ambos os DataFrames. Por exemplo, aqui o valor de id 1 estava presente com A, B e K, L no DataFrame df_row, portanto, esse id foi repetido duas vezes no DataFrame final df_merge_col com o valor repetido 12 de Feature3 que veio do DataFrame df3.

Pode acontecer de a coluna na qual você deseja mesclar os DataFrames ter nomes diferentes (diferentemente do que ocorre neste caso). Para essas mesclagens, você terá que especificar os argumentos left_on como o nome do DataFrame esquerdo e right_on como o nome do DataFrame direito, como :

df_merge_difkey = pd.merge(df_row, df3, left_on='id', right_on='id')

df_merge_difkey
  id Recurso1 Feature2 Feature3
0 1 A B 12
1 1 K L 12
2 2 C D 13
3 2 M N 13
4 3 E F 14
5 4 G H 15
6 5 I J 16
7 7 Q R 17
8 8 S T 15

Você também pode acrescentar linhas a um DataFrame passando uma Series ou um dict para a função append(), que retorna um novo DataFrame:

add_row = pd.Series(['10', 'X1', 'X2', 'X3'],
                    index=['id','Feature1', 'Feature2', 'Feature3'])

df_add_row = df_merge_col.append(add_row, ignore_index=True)

df_add_row
  id Recurso1 Feature2 Feature3
0 1 A B 12
1 1 K L 12
2 2 C D 13
3 2 M N 13
4 3 E F 14
5 4 G H 15
6 5 I J 16
7 7 Q R 17
8 8 S T 15
9 10 X1 X2 X3

Tipos de pandas Junte-se

Nesta seção, você praticará as várias lógicas de união disponíveis para mesclar DataFrames do pandas com base em alguma coluna/chave comum. A lógica por trás dessas uniões é muito parecida com a que você tem no SQL quando une tabelas.

União externa completa

O FULL OUTER JOIN combina os resultados das uniões externas esquerda e direita. O DataFrame unido conterá todos os registros de ambos os DataFrames e preencherá com NaNs as correspondências ausentes em ambos os lados. Você pode executar uma união externa completa especificando o argumento how como outer na função merge():

df_outer = pd.merge(df1, df2, on='id', how='outer')

df_outer
  id Feature1_x Feature2_x Feature1_y Feature2_y
0 1 A B K L
1 2 C D M N
2 3 E F NaN NaN
3 4 G H NaN NaN
4 5 I J NaN NaN
5 6 NaN NaN O P
6 7 NaN NaN Q R
7 8 NaN NaN S T

Você pode notar que o DataFrame resultante tinha todas as entradas de ambas as tabelas com valores NaN para correspondências ausentes em ambos os lados. No entanto, mais uma coisa a ser observada é o sufixo que foi anexado aos nomes das colunas para mostrar qual coluna veio de qual DataFrame. Os sufixos padrão são x e y; no entanto, você pode modificá-los especificando o argumento suffixes na função merge():

df_suffix = pd.merge(df1, df2, left_on='id',right_on='id',how='outer',suffixes=('_left','_right'))

df_suffix
  id Feature1_left Feature2_left Feature1_right Feature2_right
0 1 A B K L
1 2 C D M N
2 3 E F NaN NaN
3 4 G H NaN NaN
4 5 I J NaN NaN
5 6 NaN NaN O P
6 7 NaN NaN Q R
7 8 NaN NaN S T

Inner Join

O INNER JOIN produz apenas o conjunto de registros que coincidem no DataFrame A e no DataFrame B. É necessário passar inner no argumento how da função merge() para fazer o inner join:

df_inner = pd.merge(df1, df2, on='id', how='inner')

df_inner
  id Feature1_x Feature2_x Feature1_y Feature2_y
0 1 A B K L
1 2 C D M N

Junte-se à direita

O RIGHT JOIN produz um conjunto completo de registros do DataFrame B (DataFrame direito), com os registros correspondentes (quando disponíveis) no DataFrame A (DataFrame esquerdo). Se não houver correspondência, o lado direito conterá null. Você precisa passar o argumento how da função merge() para fazer a junção correta:

df_right = pd.merge(df1, df2, on='id', how='right')

df_right
  id Feature1_x Feature2_x Feature1_y Feature2_y
0 1 A B K L
1 2 C D M N
2 6 NaN NaN O P
3 7 NaN NaN Q R
4 8 NaN NaN S T

União à esquerda

O LEFT JOIN produz um conjunto completo de registros do DataFrame A (DataFrame esquerdo), com os registros correspondentes (quando disponíveis) no DataFrame B (DataFrame direito). Se não houver correspondência, o lado esquerdo conterá null. Você precisa passar left no argumento how da função merge() para fazer a junção left:

df_left = pd.merge(df1, df2, on='id', how='left')

df_left
  id Feature1_x Feature2_x Feature1_y Feature2_y
0 1 A B K L
1 2 C D M N
2 3 E F NaN NaN
3 4 G H NaN NaN
4 5 I J NaN NaN

Unindo no índice

Às vezes, talvez seja necessário executar a união nos índices ou nos rótulos de linha. Para isso, você deve especificar right_index (para os índices do DataFrame direito) e left_index (para os índices do DataFrame esquerdo) como True :

df_index = pd.merge(df1, df2, right_index=True, left_index=True)

df_index
  id_x Feature1_x Feature2_x id_y Feature1_y Feature2_y
0 1 A B 1 K L
1 2 C D 2 M N
2 3 E F 6 O P
3 4 G H 7 Q R
4 5 I J 8 S T

pandas Join

A função Pandas DataFrame.join é usada para unir quadros de dados em índices exclusivos. Você pode usar o argumento opcional `on` para unir nomes de coluna(s) no índice e como os argumentos manipulam a operação dos dois objetos. Por padrão, ele usará a junção interna. 

pandas Join Two Dataframes

Vamos unir dois quadros de dados usando .join. Fornecemos `lsuffix` e `rsuffix` para evitar o erro de sobreposição de colunas. Ele se une com base no índice, não na coluna, portanto, precisamos alterar a coluna "id" ou fornecer um sufixo.

df2.join(df3, lsuffix='_left', rsuffix='_right')

  id_left Recurso1 Feature2 id_right Feature3
0 1 K L 1 12
1 2 M N 2 13
2 6 O P 3 14
3 7 Q R 4 15
4 8 S T 5 16

Também podemos unir colunas no índice usando o argumento `on`. Para aplicar a junção com êxito, temos que df3 a coluna 'id' para indexar e fornecer o argumento `on` com a coluna 'id'. Por padrão, ele usará a união à esquerda.   

df2.join(df3.set_index('id'), on='id')

  id Recurso1 Feature2 Feature3
0 1 K L 12.0
1 2 M N 13.0
2 6 O P NaN
3 7 Q R 17.0
4 8 S T 15.0

Assim como a função merge, podemos alterar a operação de união fornecendo um argumento `how`. No nosso caso, usaremos uma união interna. 

df2.join(df3.set_index('id'), on='id', how = "inner")

  id_left Recurso1 Feature2 Feature3
0 1 K L 12
1 2 M N 13
3 7 Q R 17
4 8 S T 15

Mesclagem amigável de séries temporais

O Pandas fornece funções especiais para mesclar DataFrames de séries temporais. Talvez a mais útil e popular seja a função merge_asof(). A função merge_asof() é semelhante a uma união ordenada à esquerda, exceto pelo fato de que você faz a correspondência com a chave mais próxima em vez de chaves iguais. Para cada linha do DataFrame esquerdo, você seleciona a última linha do DataFrame direito cuja chave on é menor que a chave do esquerdo. Ambos os DataFrames devem ser classificados pela chave.

Opcionalmente, uma mesclagem asof pode realizar uma mesclagem em grupo. Isso corresponde igualmente à tecla by, além da correspondência mais próxima na tecla on.

Por exemplo, você pode ter negociações e cotações e deseja mesclá-las. Aqui, o DataFrame esquerdo é escolhido como negociações e o DataFrame direito como cotações. Elas são, a partir de agora, mescladas em horário-chave e, em termos de grupo, mescladas por seu símbolo de registro.

trades = pd.DataFrame({
    'time': pd.to_datetime(['20160525 13:30:00.023',
                            '20160525 13:30:00.038',
                            '20160525 13:30:00.048',
                            '20160525 13:30:00.048',
                            '20160525 13:30:00.048']),
    'ticker': ['MSFT', 'MSFT','GOOG', 'GOOG', 'AAPL'],
    'price': [51.95, 51.95,720.77, 720.92, 98.00],
    'quantity': [75, 155,100, 100, 100]},
    columns=['time', 'ticker', 'price', 'quantity'])

quotes = pd.DataFrame({
    'time': pd.to_datetime(['20160525 13:30:00.023',
                            '20160525 13:30:00.023',
                            '20160525 13:30:00.030',
                            '20160525 13:30:00.041',
                            '20160525 13:30:00.048',
                            '20160525 13:30:00.049',
                            '20160525 13:30:00.072',
                            '20160525 13:30:00.075']),
    'ticker': ['GOOG', 'MSFT', 'MSFT','MSFT', 'GOOG', 'AAPL', 'GOOG','MSFT'],
    'bid': [720.50, 51.95, 51.97, 51.99,720.50, 97.99, 720.50, 52.01],
    'ask': [720.93, 51.96, 51.98, 52.00,720.93, 98.01, 720.88, 52.03]},
    columns=['time', 'ticker', 'bid', 'ask'])
trades
  tempo ticker preço quantidade
0 2016-05-25 13:30:00.023 MSFT 51.95 75
1 2016-05-25 13:30:00.038 MSFT 51.95 155
2 2016-05-25 13:30:00.048 GOOG 720.77 100
3 2016-05-25 13:30:00.048 GOOG 720.92 100
4 2016-05-25 13:30:00.048 AAPL 98.00 100
quotes
  tempo ticker oferta perguntar
0 2016-05-25 13:30:00.023 GOOG 720.50 720.93
1 2016-05-25 13:30:00.023 MSFT 51.95 51.96
2 2016-05-25 13:30:00.030 MSFT 51.97 51.98
3 2016-05-25 13:30:00.041 MSFT 51.99 52.00
4 2016-05-25 13:30:00.048 GOOG 720.50 720.93
5 2016-05-25 13:30:00.049 AAPL 97.99 98.01
6 2016-05-25 13:30:00.072 GOOG 720.50 720.88
7 2016-05-25 13:30:00.075 MSFT 52.01 52.03
df_merge_asof = pd.merge_asof(trades, quotes,
              on='time',
              by='ticker')

df_merge_asof
  tempo ticker preço quantidade oferta perguntar
0 2016-05-25 13:30:00.023 MSFT 51.95 75 51.95 51.96
1 2016-05-25 13:30:00.038 MSFT 51.95 155 51.97 51.98
2 2016-05-25 13:30:00.048 GOOG 720.77 100 720.50 720.93
3 2016-05-25 13:30:00.048 GOOG 720.92 100 720.50 720.93
4 2016-05-25 13:30:00.048 AAPL 98.00 100 NaN NaN

Se você observar com atenção, poderá perceber o motivo do aparecimento do NaN na linha do ticker da AAPL. Como as cotações do DataFrame direito não tinham nenhum valor de hora inferior a 13:30:00.048 (a hora na tabela da esquerda) para o ticker AAPL, foram introduzidos NaNs nas colunas de compra e venda.

Você também pode definir um nível de tolerância predefinido para a coluna de tempo. Suponha que você só queira que asof seja mesclado dentro de 2ms entre o tempo de cotação e o tempo de negociação, então você terá que especificar o argumento de tolerância:

df_merge_asof_tolerance = pd.merge_asof(trades, quotes,
              on='time',
              by='ticker',
              tolerance=pd.Timedelta('2ms'))

df_merge_asof_tolerance
  tempo ticker preço quantidade oferta perguntar
0 2016-05-25 13:30:00.023 MSFT 51.95 75 51.95 51.96
1 2016-05-25 13:30:00.038 MSFT 51.95 155 NaN NaN
2 2016-05-25 13:30:00.048 GOOG 720.77 100 720.50 720.93
3 2016-05-25 13:30:00.048 GOOG 720.92 100 720.50 720.93
4 2016-05-25 13:30:00.048 AAPL 98.00 100 NaN NaN

Observe a diferença entre o resultado acima e o anterior. As linhas não serão mescladas se a tolerância de tempo não corresponder a 2ms.

Conclusão

Neste tutorial, você aprendeu a concatenar e mesclar DataFrames com base em várias lógicas usando as funções concat() e merge() da biblioteca pandas. No final, você também praticou a função especial merge_asof() para mesclar DataFrames de séries temporais. Ao longo do caminho, você também aprendeu a brincar com os índices dos DataFrames. Há várias outras opções que podem ser exploradas para unir DataFrames no pandas, e eu o encorajo a consultar sua fantástica documentação. Boa exploração!

Este tutorial usou a documentação do pandas para ajudar a escrevê-lo.

Se quiser saber mais sobre o pandas, faça o curso Fundamentos do pandas do DataCamp e confira nosso tutorial DataFrames in Python Pandas.

O DataCamp também tem vários outros tutoriais úteis sobre o pandas, incluindo:

Bom aprendizado!

Temas

Saiba mais sobre Python e pandas

curso

Pandas Joins for Spreadsheet Users

4 hr
3.8K
Learn how to effectively and efficiently join datasets in tabular format using the Python Pandas library.
Ver DetalhesRight Arrow
Iniciar Curso
Ver maisRight Arrow
Relacionado

tutorial

Pandas Tutorial: DataFrames em Python

Explore a análise de dados com Python. Os DataFrames do Pandas facilitam a manipulação de seus dados, desde a seleção ou substituição de colunas e índices até a remodelagem dos dados.
Karlijn Willems's photo

Karlijn Willems

20 min

tutorial

Tutorial de seleção de colunas em Python

Use o Python Pandas e selecione colunas de DataFrames. Siga nosso tutorial com exemplos de código e aprenda diferentes maneiras de selecionar seus dados hoje mesmo!
DataCamp Team's photo

DataCamp Team

7 min

tutorial

Tutorial do Python pandas: O guia definitivo para iniciantes

Você está pronto para começar sua jornada com os pandas? Aqui está um guia passo a passo sobre como você pode começar.
Vidhi Chugh's photo

Vidhi Chugh

15 min

tutorial

Tutorial do For Loops em Python

Saiba como implementar For Loops em Python para iterar uma sequência ou as linhas e colunas de um dataframe do pandas.
Aditya Sharma's photo

Aditya Sharma

5 min

tutorial

Tutorial de funções Python

Um tutorial sobre funções em Python que aborda como escrever funções, como chamá-las e muito mais!
Karlijn Willems's photo

Karlijn Willems

14 min

tutorial

Tutorial de manipulação de dados categóricos de aprendizado de máquina com Python

Aprenda os truques comuns para lidar com dados categóricos e pré-processá-los para criar modelos de aprendizado de máquina!
Moez Ali's photo

Moez Ali

28 min

See MoreSee More