2013-07-04 19 views
10

Vorrei rimuovere completamente un livello da un MultiIndexRimuovere un livello da un panda MultiIndex

import pandas as pd 
tuples = [(0, 100, 1000),(0, 100, 1001),(0, 100, 1002), (1, 101, 1001)] 
index_3levels=pd.MultiIndex.from_tuples(tuples,names=["l1","l2","l3"]) 
print index_3levels.levels 
[Int64Index([0, 1], dtype=int64), Int64Index([100, 101], dtype=int64), Int64Index([1000, 1001, 1002], dtype=int64)] 

vorrei estrarre i primi 2 livelli, per ottenere:

print index_2levels 
MultiIndex 
[(0, 100), (1, 101)] 

droplevel gocce il livello ma mantiene i duplicati:

print index_3levels.droplevel("l3") 
MultiIndex 
[(0, 100), (0, 100), (0, 100), (1, 101)] 

In linea di principio potrei cal l unique per rimuoverli. Tuttavia non sembra l'approccio giusto. Esiste un metodo più diretto?

risposta

7

Questo potrebbe essere un miglioramento a droplevel, forse passando uniquify=True

In [77]: MultiIndex.from_tuples(index_3levels.droplevel('l3').unique()) 
Out[77]: 
MultiIndex 
[(0, 100), (1, 101)] 

Ecco un altro modo per farlo

Innanzitutto creare alcuni dati

In [226]: def f(i): 
      return [(i,100,1000),(i,100,1001),(i,100,1002),(i+1,101,1001)] 

In [227]: l = [] 

In [228]: for i in range(1000000): 
      l.extend(f(i)) 

In [229]: index_3levels=pd.MultiIndex.from_tuples(l,names=["l1","l2","l3"]) 

In [230]: len(index_3levels) 
Out[230]: 4000000 

il metodo illustrato sopra

In [238]: %timeit MultiIndex.from_tuples(index_3levels.droplevel(level='l3').unique()) 
1 loops, best of 3: 2.26 s per loop 

Dividiamo l'indice oltre a 2 componenti, L1, L2 e uniquify, molto più veloce da unico questi come questi sono Int64Index

In [249]: l2 = index_3levels.droplevel(level='l3').droplevel(level='l1').unique() 

In [250]: %timeit index_3levels.droplevel(level='l3').droplevel(level='l1').unique() 
10 loops, best of 3: 35.3 ms per loop 

In [251]: l1 = index_3levels.droplevel(level='l3').droplevel(level='l2').unique() 

In [252]: %timeit index_3levels.droplevel(level='l3').droplevel(level='l2').unique() 
10 loops, best of 3: 52.2 ms per loop 

In [253]: len(l1) 
Out[253]: 1000001 

In [254]: len(l2) 
Out[254]: 2 

Rimontare

In [255]: %timeit MultiIndex.from_arrays([ np.repeat(l1,len(l2)), np.repeat(l2,len(l1)) ]) 
10 loops, best of 3: 183 ms per loop 

tempo totale circa 270ms, abbastanza buona velocità. Nota che penso che l'ordinamento potrebbe essere diverso, ma penso che una combinazione di np.repeate/np.tile funzionerà

+0

Un'altra idea potrebbe essere un miglioramento per restituire un oggetto della stessa classe. –

+0

Grazie, tuttavia, mi chiedo se esiste una soluzione migliore, che non richiede l'esecuzione di 'unique', che è piuttosto costoso. Dopotutto voglio solo estrarre 2 livelli del 3 nel 'MultiIndex', non creare un nuovo oggetto. –

+0

univoco è in realtà piuttosto veloce qui; qual è il tuo obiettivo finale? – Jeff

Problemi correlati