Corso
Hai mai provato a risolvere una challenge su Kaggle? Se sì, avrai notato che nella maggior parte delle challenge i dati forniti sono distribuiti su più file, con alcune colonne presenti in più di un file. Bene, qual è la prima cosa che ti viene in mente? Unirli, ovviamente!
In questo tutorial metterai in pratica alcune tecniche standard di join in pandas. In particolare, imparerai a:
- Concatenare DataFrame per righe e per colonne.
- Effettuare merge di DataFrame su chiavi specifiche con diverse logiche di join come left join, inner join, ecc.
- Eseguire join di DataFrame per indice.
- Usare il merging ottimizzato per serie temporali offerto da pandas
Lungo il percorso, imparerai anche alcuni trucchi utili prima e dopo l'operazione di join.
TL;DR
- Usa
pd.concat()per impilare i DataFrame verticalmente (righe) o orizzontalmente (colonne) - Usa
pd.merge()per unire DataFrame su colonne comuni, in modo simile ai join in SQL - Specifica il tipo di join con il parametro
how:'inner','outer','left'o'right' - Usa
.join()per i join basati sull'indice dei DataFrame - Usa
pd.merge_asof()per dati di serie temporali quando ti serve il matching con la chiave più vicina
Join in pandas
Unire e fare merge dei DataFrame è il processo centrale per iniziare analisi dei dati e attività di machine learning. È uno degli strumenti che ogni Data Analyst o Data Scientist dovrebbe padroneggiare perché, quasi sempre, i dati arrivano da più fonti e file. Potresti dover portare tutti i dati in un unico posto con una certa logica di join, e poi iniziare l'analisi. Chi lavora con i join in SQL conosce bene l'importanza di questo compito. Anche se vuoi costruire modelli di machine learning su alcuni dati, potresti dover unire più file CSV in un unico DataFrame.
Per fortuna hai a disposizione la libreria più popolare in Python, pandas a venirti in aiuto! pandas offre diverse funzionalità per combinare facilmente Series e DataFrame con vari tipi di logica insiemistica sugli indici e funzionalità di algebra relazionale per le operazioni di tipo join/merge.
Esegui e modifica il codice da questo tutorial online
Esegui codiceConcatenare in pandas
Inizia importando la libreria che userai in tutto il tutorial: pandas
import pandas as pd
Eseguirai tutte le operazioni in questo tutorial su DataFrame di esempio che creerai. Per creare un DataFrame, puoi usare un dizionario Python come:
dummy_data1 = {
'id': ['1', '2', '3', '4', '5'],
'Feature1': ['A', 'C', 'E', 'G', 'I'],
'Feature2': ['B', 'D', 'F', 'H', 'J']}
Qui, le chiavi del dizionario dummy_data1 sono i nomi delle colonne e i valori nelle liste sono i dati corrispondenti a ciascuna osservazione o riga. Per trasformarlo in un DataFrame pandas, userai la funzione DataFrame() di pandas, insieme all'argomento columns per assegnare i nomi alle colonne:
df1 = pd.DataFrame(dummy_data1, columns = ['id', 'Feature1', 'Feature2'])
df1
| id | Feature1 | Feature2 | |
|---|---|---|---|
| 0 | 1 | A | B |
| 1 | 2 | C | D |
| 2 | 3 | E | F |
| 3 | 4 | G | H |
| 4 | 5 | I | J |
Come puoi notare, ora hai un DataFrame con tre colonne id, Feature1 e Feature2. C'è un'ulteriore colonna senza nome che pandas crea intrinsecamente come etichette di riga. Come per il precedente DataFrame df1, creerai altri due DataFrame 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 | Feature1 | 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()
Per concatenare semplicemente i DataFrame per riga puoi usare la funzione concat() di pandas. Dovrai passare i nomi dei DataFrame in una lista come argomento della funzione concat():
df_row = pd.concat([df1, df2])
df_row
| id | Feature1 | 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 |
Puoi notare che i due DataFrame df1 e df2 sono ora concatenati in un unico DataFrame df_row per riga. Tuttavia, le etichette di riga sembrano sbagliate. Se vuoi che le etichette di riga si adeguino automaticamente in base al join, devi impostare l'argomento ignore_index a True quando chiami la funzione concat():
df_row_reindex = pd.concat([df1, df2], ignore_index=True)
df_row_reindex
| id | Feature1 | 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 |
Ora le etichette di riga sono corrette!
pandas ti offre anche un'opzione per etichettare i DataFrame, dopo la concatenazione, con una chiave in modo da sapere quali dati provengono da quale DataFrame. Puoi ottenere lo stesso passando l'argomento aggiuntivo keys che specifica i nomi delle etichette dei DataFrame in una lista. Qui eseguirai la stessa concatenazione con le chiavi x e y per i DataFrame df1 e df2 rispettivamente.
frames = [df1,df2]
df_keys = pd.concat(frames, keys=['x', 'y'])
df_keys
| id | Feature1 | 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 |
Indicare le chiavi rende anche facile recuperare i dati corrispondenti a un particolare DataFrame. Puoi recuperare i dati del DataFrame df2, che aveva l'etichetta y, usando il metodo loc:
df_keys.loc['y']
| id | Feature1 | Feature2 | |
|---|---|---|---|
| 0 | 1 | K | L |
| 1 | 2 | M | N |
| 2 | 6 | O | P |
| 3 | 7 | Q | R |
| 4 | 8 | S | T |
Puoi anche passare un dizionario a concat(); in questo caso, le chiavi del dizionario verranno usate per l'argomento keys (a meno che non vengano specificate altre chiavi):
pieces = {'x': df1, 'y': df2}
df_piece = pd.concat(pieces)
df_piece
| id | Feature1 | 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 |
Vale la pena notare che concat() crea una copia completa dei dati e usarla ripetutamente può avere un impatto significativo sulle prestazioni. Per operazioni su larga scala, valuta di esplorare pandas 2.0 vs polars per manipolazione dati ad alte prestazioni. Se devi usare l'operazione su diversi dataset, usa una list comprehension.
frames = [ process_your_file(f) for f in files ]
result = pd.concat(frames)
Per concatenare DataFrame per colonna, puoi specificare il parametro axis come 1:
df_col = pd.concat([df1,df2], axis=1)
df_col
| id | Feature1 | Feature2 | id | Feature1 | 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 |
Eseguire merge di DataFrame in pandas
Un'altra operazione molto comune sui DataFrame è il merge. Due DataFrame possono contenere tipi diversi di informazioni sulla stessa entità ed essere collegati da qualche caratteristica/colonna comune. Per unire questi DataFrame, pandas fornisce diverse funzioni come concat(), merge(), join(), ecc. In questa sezione, farai pratica con la funzione merge() di pandas.
Puoi unire i DataFrame df_row (che hai creato concatenando df1 e df2 per riga) e df3 sulla colonna (o chiave) comune id. Per farlo, passa i nomi dei DataFrame e un argomento aggiuntivo on con il nome della colonna comune, qui id, alla funzione merge():
df_merge_col = pd.merge(df_row, df3, on='id')
df_merge_col
| id | Feature1 | 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 |
Puoi notare che i DataFrame ora sono uniti in un unico DataFrame in base ai valori comuni presenti nella colonna id di entrambi. Per esempio, qui il valore id 1 era presente con A, B e con K, L nel DataFrame df_row, quindi questo id è stato ripetuto due volte nel DataFrame finale df_merge_col con il valore ripetuto 12 di Feature3 proveniente dal DataFrame df3.
Potrebbe capitare che la colonna su cui vuoi effettuare il merge abbia nomi diversi (a differenza di questo caso). Per tali merge, dovrai specificare gli argomenti left_on come nome della colonna del DataFrame di sinistra e right_on come nome della colonna del DataFrame di destra, così:
df_merge_difkey = pd.merge(df_row, df3, left_on='id', right_on='id')
df_merge_difkey
| id | Feature1 | 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 |
Puoi anche aggiungere righe a un DataFrame usando pd.concat(). Prima, crea un nuovo DataFrame con i dati della riga, poi concatenalo con il DataFrame originale:
add_row = pd.DataFrame([['10', 'X1', 'X2', 'X3']],
columns=['id', 'Feature1', 'Feature2', 'Feature3'])
df_add_row = pd.concat([df_merge_col, add_row], ignore_index=True)
df_add_row
| id | Feature1 | 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 |
Tipi di join in pandas
In questa sezione metterai in pratica le varie logiche di join disponibili per unire DataFrame pandas basandoti su una colonna/chiave comune. La logica dietro questi join è molto simile a quella che hai in SQL quando unisci tabelle. Se hai familiarità con le differenze tra inner e outer join in SQL, ritroverai concetti familiari.
| Join Type | SQL Equivalent | Result | Use Case |
|---|---|---|---|
inner |
INNER JOIN | Solo le righe corrispondenti in entrambi i DataFrame | Quando vuoi solo i record presenti in entrambe le tabelle |
left |
LEFT OUTER JOIN | Tutte le righe da sinistra + corrispondenze da destra | Mantenere tutti i record dal DataFrame principale |
right |
RIGHT OUTER JOIN | Tutte le righe da destra + corrispondenze da sinistra | Mantenere tutti i record dal DataFrame secondario |
outer |
FULL OUTER JOIN | Tutte le righe da entrambi i DataFrame | Quando ti serve l'unione completa di entrambe le tabelle |
Full Outer Join
Il FULL OUTER JOIN combina i risultati del left e del right outer join. Il DataFrame unito conterrà tutti i record di entrambi i DataFrame e riempirà con valori NaN le mancate corrispondenze da una parte o dall'altra. Puoi eseguire un full outer join specificando l'argomento how come outer nella funzione 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 |
Puoi notare che il DataFrame risultante contiene tutte le voci di entrambe le tabelle con valori NaN per le mancate corrispondenze da una parte o dall'altra. Un'altra cosa da notare è il suffisso aggiunto ai nomi delle colonne per indicare da quale DataFrame provengono. I suffissi predefiniti sono x e y, ma puoi modificarli specificando l'argomento suffixes nella funzione 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
L'INNER JOIN produce solo l'insieme di record che combaciano sia nel DataFrame A che nel DataFrame B. Devi passare inner nell'argomento how della funzione merge() per fare l'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 |
Right Join
Il RIGHT JOIN produce l'insieme completo dei record dal DataFrame B (DataFrame di destra), con i record corrispondenti (dove disponibili) nel DataFrame A (DataFrame di sinistra). Se non c'è corrispondenza, il lato destro conterrà valori null. Devi passare right nell'argomento how della funzione merge() per fare il right join:
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 |
Left Join
Il LEFT JOIN produce l'insieme completo dei record dal DataFrame A (DataFrame di sinistra), con i record corrispondenti (dove disponibili) nel DataFrame B (DataFrame di destra). Se non c'è corrispondenza, il lato sinistro conterrà valori null. Devi passare left nell'argomento how della funzione merge() per fare il left join:
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 |
Join sugli indici
A volte potresti dover eseguire il join sugli indici o sulle etichette di riga. Per farlo, devi specificare right_index (per gli indici del DataFrame di destra) e left_index (per gli indici del DataFrame di sinistra) come 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
Il metodo DataFrame.join() di pandas si usa per unire DataFrame su indici univoci. Puoi usare l'argomento opzionale `on` per unire i nomi di colonna sugli indici e l'argomento how per gestire il tipo di operazione tra i due oggetti. Per impostazione predefinita, usa l'inner join.
pandas: unire due DataFrame
Uniamo due data frame usando .join. Abbiamo fornito `lsuffix` e `rsuffix` per evitare l'errore dovuto a colonne sovrapposte. Esegue il join basandosi sull'indice, non sulla colonna, quindi dobbiamo o cambiare la colonna 'id' o fornire un suffisso.
df2.join(df3, lsuffix='_left', rsuffix='_right')
| id_left | Feature1 | 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 |
Possiamo anche unire colonne sull'indice usando l'argomento `on`. Per applicare correttamente il join, dobbiamo impostare la colonna 'id' di df3 come indice e fornire l'argomento `on` con la colonna 'id'. Per impostazione predefinita, userà il left join.
df2.join(df3.set_index('id'), on='id')
| id | Feature1 | 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 |
Come per la funzione merge, possiamo cambiare il tipo di join fornendo un argomento `how`. Nel nostro caso, useremo un inner join.
df2.join(df3.set_index('id'), on='id', how = "inner")
| id_left | Feature1 | Feature2 | Feature3 | |
|---|---|---|---|---|
| 0 | 1 | K | L | 12 |
| 1 | 2 | M | N | 13 |
| 3 | 7 | Q | R | 17 |
| 4 | 8 | S | T | 15 |
Merging per serie temporali
pandas fornisce funzioni speciali per unire DataFrame di serie temporali. Forse la più utile e popolare è la funzione merge_asof(). merge_asof() è simile a un left join ordinato, tranne per il fatto che fai il match sulla chiave più vicina invece che su chiavi uguali. Per ogni riga nel DataFrame di sinistra, selezioni l'ultima riga nel DataFrame di destra la cui chiave on è minore della chiave di sinistra. Entrambi i DataFrame devono essere ordinati per chiave.
Facoltativamente un asof merge può eseguire un merge per gruppo. In questo caso, oltre alla corrispondenza più vicina sulla chiave on, si richiede l'uguaglianza sulla chiave by.
Per esempio, potresti avere trades e quotes, e volerli unire con asof. Qui il DataFrame di sinistra è trades e quello di destra è quotes. Sono uniti con asof sulla chiave time e per gruppo in base al loro ticker.
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
| time | ticker | price | quantity | |
|---|---|---|---|---|
| 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
| time | ticker | bid | ask | |
|---|---|---|---|---|
| 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
| time | ticker | price | quantity | bid | ask | |
|---|---|---|---|---|---|---|
| 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 |
Osservando con attenzione, puoi notare il motivo per cui compaiono i NaN nella riga del ticker AAPL. Poiché nel DataFrame di destra quotes non c'era alcun valore di time minore di 13:30:00.048 (il time nella tabella di sinistra) per il ticker AAPL, sono stati inseriti NaN nelle colonne bid e ask.
Puoi anche impostare un livello di tolleranza predefinito per la colonna temporale. Supponiamo che tu voglia unire con asof solo entro 2 ms tra l'orario del quote e l'orario del trade, allora dovrai specificare l'argomento tolerance:
df_merge_asof_tolerance = pd.merge_asof(trades, quotes,
on='time',
by='ticker',
tolerance=pd.Timedelta('2ms'))
df_merge_asof_tolerance
| time | ticker | price | quantity | bid | ask | |
|---|---|---|---|---|---|---|
| 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 |
Nota la differenza tra il risultato qui sopra e quello precedente. Le righe non vengono unite se la tolleranza temporale non rientra nei 2 ms.
Conclusione
In questo tutorial hai imparato a concatenare e a fare merge di DataFrame in base a diverse logiche usando le funzioni concat() e merge() della libreria pandas. Alla fine, hai anche esercitato la funzione speciale merge_asof() per unire DataFrame di serie temporali. Lungo il percorso, hai anche imparato a lavorare con gli indici dei DataFrame. Ci sono molte altre opzioni che puoi esplorare per unire DataFrame in pandas, e ti incoraggio a consultare la sua fantastica documentazione. Buona esplorazione!
Questo tutorial ha utilizzato questa documentazione di pandas come riferimento.
Se vuoi saperne di più su pandas, segui il corso di DataCamp Data Manipulation with pandas e dai un'occhiata al nostro Tutorial sui DataFrame in Python con pandas.
DataCamp ha anche diversi altri utili tutorial su pandas, tra cui:
- Importare dati CSV in pandas
- Aggiungere colonne in pandas
- Ordinare i valori in pandas
- Rimuovere duplicati in pandas con
drop_duplicates - Raggruppare dati con pandas groupby
- Reimpostare gli indici di un DataFrame in pandas
Buono studio!
FAQs
Qual è la differenza tra merge() e join() in pandas?
merge() è più flessibile e può unire DataFrame su qualsiasi colonna, in modo simile ai join in SQL. join() è pensato principalmente per i join sugli indici ed è un metodo di convenienza che internamente chiama merge(). Usa merge() quando unisci su colonne e join() quando le chiavi di join sono già impostate come indici.
Come faccio a fare il merge di DataFrame su più colonne in pandas?
Passa una lista di nomi di colonne al parametro on: pd.merge(df1, df2, on=['col1', 'col2']). Se i nomi delle colonne differiscono tra i DataFrame, usa left_on e right_on con liste: pd.merge(df1, df2, left_on=['a', 'b'], right_on=['c', 'd']).
Cosa succede ai valori mancanti quando faccio il merge dei DataFrame?
Il comportamento dipende dal tipo di join. Con inner le righe senza corrispondenze vengono escluse. Con i join left, right o outer, le righe senza match vengono mantenute e riempite con NaN nelle colonne dell'altro DataFrame. Puoi gestirle usando fillna() o dropna() dopo il merge.
Quando dovrei usare concat() invece di merge() in pandas?
Usa concat() per impilare i DataFrame verticalmente (aggiungendo righe) o orizzontalmente (aggiungendo colonne) in base all'allineamento degli indici. Usa merge() quando devi combinare DataFrame basandoti su valori di colonne comuni, in modo simile ai join relazionali in SQL. Pensa a concat() come a "incollare" i DataFrame, mentre merge() serve per i join relazionali.
Come gestisco i nomi di colonna duplicati dopo un merge in pandas?
Per impostazione predefinita, pandas aggiunge i suffissi _x e _y ai nomi di colonne duplicate. Personalizzali con il parametro suffixes: pd.merge(df1, df2, on='id', suffixes=('_left', '_right')). Dopo il merge, puoi rinominare le colonne con df.rename(columns={'old': 'new'}) o eliminare i duplicati con df.drop(columns=['col_y']).
Qual è la differenza tra merge() e join() in pandas?
merge() è più flessibile e può unire DataFrame su qualsiasi colonna, in modo simile ai join in SQL. join() è pensato principalmente per i join sugli indici ed è un metodo di convenienza che internamente chiama merge(). Usa merge() quando unisci su colonne e join() quando le chiavi di join sono già impostate come indici.
Come faccio a fare il merge di DataFrame su più colonne in pandas?
Passa una lista di nomi di colonne al parametro on: pd.merge(df1, df2, on=['col1', 'col2']). Se i nomi delle colonne differiscono tra i DataFrame, usa left_on e right_on con liste: pd.merge(df1, df2, left_on=['a', 'b'], right_on=['c', 'd']).
Cosa succede ai valori mancanti quando faccio il merge dei DataFrame?
Il comportamento dipende dal tipo di join. Con inner le righe senza corrispondenze vengono escluse. Con i join left, right o outer, le righe senza match vengono mantenute e riempite con NaN nelle colonne dell'altro DataFrame. Puoi gestirle usando fillna() o dropna() dopo il merge.
Quando dovrei usare concat() invece di merge() in pandas?
Usa concat() per impilare i DataFrame verticalmente (aggiungendo righe) o orizzontalmente (aggiungendo colonne) in base all'allineamento degli indici. Usa merge() quando devi combinare DataFrame basandoti su valori di colonne comuni, in modo simile ai join relazionali in SQL. Pensa a concat() come a "incollare" i DataFrame, mentre merge() serve per i join relazionali.
Come gestisco i nomi di colonna duplicati dopo un merge in pandas?
Per impostazione predefinita, pandas aggiunge i suffissi _x e _y ai nomi di colonne duplicate. Personalizzali con il parametro suffixes: pd.merge(df1, df2, on='id', suffixes=('_left', '_right')). Dopo il merge, puoi rinominare le colonne con df.rename(columns={'old': 'new'}) o eliminare i duplicati con df.drop(columns=['col_y']).

