Come mantenere l'indice quando si utilizza l'unione dei panda


126

Vorrei unire due DataFramese mantenere l'indice del primo fotogramma come indice del set di dati unito. Tuttavia, quando eseguo l'unione, il DataFrame risultante ha un indice intero. Come posso specificare che voglio mantenere l'indice dal data frame di sinistra?

In [4]: a = pd.DataFrame({'col1': {'a': 1, 'b': 2, 'c': 3}, 
                          'to_merge_on': {'a': 1, 'b': 3, 'c': 4}})

In [5]: b = pd.DataFrame({'col2': {0: 1, 1: 2, 2: 3}, 
                          'to_merge_on': {0: 1, 1: 3, 2: 5}})

In [6]: a
Out[6]:
   col1  to_merge_on
a     1            1
b     2            3
c     3            4

In [7]: b
Out[7]:
   col2  to_merge_on
0     1            1
1     2            3
2     3            5

In [8]: a.merge(b, how='left')
Out[8]:
   col1  to_merge_on  col2
0     1            1   1.0
1     2            3   2.0
2     3            4   NaN

In [9]: _.index
Out[9]: Int64Index([0, 1, 2], dtype='int64')

EDIT: passa al codice di esempio che può essere facilmente riprodotto


2
se ti unisci su una colonna specifica, non è chiaro quali indici utilizzare (nel caso siano entrambi diversi).
bonobo

Risposte:


161
In [5]: a.reset_index().merge(b, how="left").set_index('index')
Out[5]:
       col1  to_merge_on  col2
index
a         1            1     1
b         2            3     2
c         3            4   NaN

Nota: per alcune operazioni di unione a sinistra potresti ritrovarti con più righe se ci sono più corrispondenze tra ae be dovrai eseguire la deduplicazione ( documentazione per la deduplicazione ). Questo è il motivo per cui i panda non tengono l'indice per te.


4
Molto intelligente. a.merge (b, how = "left"). set_index (a.index) funziona anche, ma sembra meno robusto (poiché la prima parte di esso perde i valori dell'indice a prima di ripristinarli.)
DanB

11
Per questo caso particolare, quelli sono equivalenti. Ma per molte operazioni di unione, il frame risultante non ha lo stesso numero di righe del aframe originale . reset_index sposta l'indice in una colonna normale e set_index da questa colonna dopo l'unione si prende cura anche quando le righe di a vengono duplicate / rimosse a causa dell'operazione di unione.
Wouter Overmeire

1
@Wouter Mi piacerebbe sapere perché un'unione a sinistra verrà reindicizzata per impostazione predefinita. Dove posso saperne di più?
Matteo

7
Bello! Per evitare di specificare esplicitamente il nome-indice che uso a.reset_index().merge(b, how="left").set_index(a.index.names).
Truls

3
I panda pensavano che l'API colpisse di nuovo.
Henry Henrinson

7

Puoi fare una copia dell'indice sul dataframe sinistro e fare l'unione.

a['copy_index'] = a.index
a.merge(b, how='left')

Ho trovato questo semplice metodo molto utile mentre lavoravo con dataframe di grandi dimensioni e usando pd.merge_asof()(odd.merge_asof() ).

Questo approccio sarebbe migliore quando la reimpostazione dell'indice è costosa (frame di dati di grandi dimensioni).


1
Questa è la migliore risposta. Ci sono molti motivi per cui vorresti preservare i tuoi vecchi indici durante un'unione (e la risposta accettata non conserva gli indici, li reimposta). È utile quando si tenta di unire più di 2 dataframe e così via ...
Marses

2
Soluzione superiore in quanto preserva il nome dell'indice (originale)
Martien Lubberink

upvoted ma solo diffidare di un avvertimento, quando si utilizza multi-index, i tuoi indici verranno memorizzati come una tupla in una singola colonna chiamata [copy_index]
geekidharsh

6

Esiste una soluzione non pd.merge. Utilizzando mapeset_index

In [1744]: a.assign(col2=a['to_merge_on'].map(b.set_index('to_merge_on')['col2']))
Out[1744]:
   col1  to_merge_on  col2
a     1            1   1.0
b     2            3   2.0
c     3            4   NaN

E non introduce un indexnome fittizio per l'indice.


1
Questo sembra superiore alla risposta accettata in quanto probabilmente funzionerà meglio con casi limite come gli indici multipli. Qualcuno può commentare questo?
Ballpoint

1
domanda, cosa succede se è necessario assegnare più colonne, questo approccio funzionerebbe o è limitato a un solo campo?
Yuca

@ Yuca: Questo probabilmente non funzionerà con più colonne, poiché quando si sottoinsiemi più colonne si finisce con un pd.Dataframee non a pd.Series. Il .map()metodo è definito solo per pd.Series. Questo significa che: a[['to_merge_on_1', 'to_merge_on_2']].map(...)non funzionerà.
Dataman

4
df1 = df1.merge(
        df2, how="inner", left_index=True, right_index=True
    )

Ciò consente di preservare l'indice di df1


Sembra funzionare, ma quando lo uso con on=list_of_cols], contraddice la documentazione: If joining columns on columns, the DataFrame indexes *will be ignored*. Uno tra l'utilizzo di indici e colonne ha la precedenza?
Itamar Katz

0

Penso di aver trovato una soluzione diversa. Mi stavo unendo alla tabella di sinistra sul valore dell'indice e alla tabella di destra su un valore di colonna basato sull'indice della tabella di sinistra. Quello che ho fatto è stata una normale unione:

First10ReviewsJoined = pd.merge(First10Reviews, df, left_index=True, right_on='Line Number')

Quindi ho recuperato i nuovi numeri di indice dalla tabella unita e li ho inseriti in una nuova colonna denominata Sentiment Line Number:

First10ReviewsJoined['Sentiment Line Number']= First10ReviewsJoined.index.tolist()

Quindi ho reimpostato manualmente l'indice sull'indice della tabella di sinistra originale basato sulla colonna preesistente chiamata Numero di riga (il valore della colonna a cui mi sono unito dall'indice della tabella di sinistra):

First10ReviewsJoined.set_index('Line Number', inplace=True)

Quindi rimosso il nome di indice del numero di riga in modo che rimanga vuoto:

First10ReviewsJoined.index.name = None

Forse un po 'un trucco, ma sembra funzionare bene e relativamente semplice. Inoltre, immagina che riduca il rischio di duplicare / rovinare i tuoi dati. Si spera che tutto abbia un senso.


0

un'altra semplice opzione è rinominare l'indice in quello che era prima:

a.merge(b, how="left").set_axis(a.index)

merge conserva l'ordine nel dataframe 'a', ma reimposta semplicemente l'indice in modo che venga salvato per usare set_axis

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.