2013-07-23 15 views
9

Nei dati con cui sto lavorando l'indice è composto, ovvero ha sia il nome dell'elemento che un timestamp, ad es. [email protected]|2013-05-07 05:52:51 +0200.Conversione di indice in MultiIndex (indice gerarchico) in Panda

Voglio fare l'indicizzazione gerarchica, in modo che le stesse e-mail siano raggruppate insieme, quindi ho bisogno di convertire un indice DataFrame in un MultiIndex (ad esempio per la voce sopra - ([email protected], 2013-05-07 05:52:51 +0200)).

Qual è il metodo più conveniente per farlo?

risposta

9

volta che abbiamo un dataframe

import pandas as pd 
df = pd.read_csv("input.csv", index_col=0) # or from another source 

e una mappatura funzione ogni indice di una tupla (di seguito, è per esempio da questa domanda)

def process_index(k): 
    return tuple(k.split("|")) 

possiamo creare un indice gerarchico nel modo seguente:

df.index = pd.MultiIndex.from_tuples([process_index(k) for k,v in df.iterrows()]) 

Un approccio alternativo consiste nel creare due colonne e impostarle come l'indice (l'indice originale verrà abbandonato):

df['e-mail'] = [x.split("|")[0] for x in df.index] 
df['date'] = [x.split("|")[1] for x in df.index] 
df = df.set_index(['e-mail', 'date']) 

o anche più breve

df['e-mail'], df['date'] = zip(*map(process_index, df.index)) 
df = df.set_index(['e-mail', 'date']) 
+0

Questo è stato molto utile. Ma, per quanto posso vedere, quando si chiama set_index() il valore predefinito è inplace = False, quindi si deve usare inplace = True o altrimenti assegnare df a se stesso. – Moot

+0

@Moot Grazie, aggiornato. O un refuso o back (4 anni fa) era 'inplace' di default. –

+0

Ottimo! Ma c'erano due posti: controlla il primo frammento di codice ... – Moot

2

mia preferenza sarebbe di leggere inizialmente questo come una colonna (vale a dire non come un indice), quindi è possibile utilizzare il metodo str scissione:

csv = '\n'.join(['[email protected]|2013-05-07 05:52:51 +0200, 42'] * 3) 
df = pd.read_csv(StringIO(csv), header=None) 

In [13]: df[0].str.split('|') 
Out[13]: 
0 [[email protected], 2013-05-07 05:52:51 +0200] 
1 [[email protected], 2013-05-07 05:52:51 +0200] 
2 [[email protected], 2013-05-07 05:52:51 +0200] 
Name: 0, dtype: object 

E poi alimentare questo in un MultiIndex (forse questo può essere fatto più pulito):?

m = pd.MultiIndex.from_arrays(zip(*df[0].str.split('|'))) 

Eliminare la colonna 0 e impostare l'indice al nuovo MultiIndex:

del df[0] 
df.index = m 

In [17]: df 
Out[17]: 
              1 
[email protected] 2013-05-07 05:52:51 +0200 42 
       2013-05-07 05:52:51 +0200 42 
       2013-05-07 05:52:51 +0200 42 
3

In pandas>=0.16.0, possiamo usare il .str di accesso su indici. Questo rende il seguente possibile:

df.index = pd.MultiIndex.from_tuples(df.index.str.split('|').tolist()) 

(Nota: ho provato il più intuitivo: pd.MultiIndex.from_arrays(df.index.str.split('|')) ma per qualche ragione che mi dà errori.)

Problemi correlati