2013-05-20 10 views
22

C'è un modo per unire su un singolo livello di un MultiIndex senza reimpostare l'indice?Unisci a livello singolo di MultiIndex

Ho una tabella "statica" di valori tempo-invarianti, indicizzati da un ObjectID, e ho una tabella "dinamica" di campi variabili nel tempo, indicizzati da ObjectID + Date. Mi piacerebbe unirmi a questi tavoli insieme.

In questo momento, il meglio che posso pensare è:

dynamic.reset_index().merge(static, left_on=['ObjectID'], right_index=True) 

Tuttavia, la tabella dinamica è molto grande, e io non voglio avere a muck in giro con il suo indice in modo da combinare la valori.

+0

Che cosa succede se si è creato una colonna aggiuntiva con il livello del MultiIndex si desidera partecipare su e poi fuso/uniti su che su questo? Potrebbe non essere totalmente efficiente, ma almeno si mantiene l'indice. –

+0

Sì, funzionerebbe. Sarebbe costato un po 'di memoria e non avrebbe aiutato la velocità. A quel punto, però, penso che potrei anche eliminare completamente l'indice, se non contribuirà a velocizzare le fusioni. –

+2

problema github corrispondente https://github.com/pydata/pandas/issues/3662 –

risposta

9

Sì, dal momento che i panda 0.14.0, è ora possibile unire un singolarmente -indicato DataFrame con un livello di DataFrame con più indici utilizzando .join.

df1.join(df2, how='inner') # how='outer' keeps all records from both data frames 

The 0.14 pandas docs descrive questo come equivalente ma più memoria efficace e più rapido:

merge(df1.reset_index(), 
     df2.reset_index(), 
     on=['index1'], 
     how='inner' 
    ).set_index(['index1','index2']) 

I documenti menzionano anche che .join non può essere utilizzato per unire due DataFrames multiindexed su un unico livello e dalla GitHub discussione tracker per il problema precedente, sembra che questo non sia di priorità da implementare:

quindi mi sono unito al join singolo, vedi # 6363 ; insieme ad alcuni documenti su come fare un multi-multi join. È abbastanza complicato implementare effettivamente lo . e IMHO non ne vale la pena visto che in realtà non cambia l'utilizzo/la velocità della memoria di un numero pari a .

Tuttavia, c'è una conversazione GitHub su questo, dove c'è stato qualche recente sviluppo https://github.com/pydata/pandas/issues/6360. È anche possibile ottenere ciò reimpostando gli indici come menzionato in precedenza e descritti anche nei documenti.

+1

Per il primo esempio, come si seleziona il livello del MultiIndex da utilizzare per il join? –

+1

nvm, il [docs] (http://pandas.pydata.org/pandas-docs/stable/merging.html#joining-a-single-index-to-a-multi-index) dice che si basa su il livello di indice con lo stesso nome dell'indice a livello singolo. –

+0

E i join sono estremamente veloci nei panda –

2

Mi aggiro di questo reindicando la fusione di dataframe per avere il multiindex completo in modo che sia possibile un join sinistro.

# Create the left data frame 
import pandas as pd 
idx = pd.MultiIndex(levels=[['a','b'],['c','d']],labels=[[0,0,1,1],[0,1,0,1]], names=['lvl1','lvl2']) 
df = pd.DataFrame([1,2,3,4],index=idx,columns=['data']) 

#Create the factor to join to the data 'left data frame' 
newFactor = pd.DataFrame(['fact:'+str(x) for x in df.index.levels[0]], index=df.index.levels[0], columns=['newFactor']) 

Do il join sul sottoindice dalla reindicizzazione il dataframe newFactor per contenere l'indice del frame di dati sinistra

df.join(newFactor.reindex(df.index,level=0)) 
1

vorrei usare la mappatura per una singola colonna:

df1['newcol'] = df1.index.get_level_values(-1).map(lambda x: df2.newcol[x]) 
Problemi correlati