2013-07-23 8 views
9

W danych, z którymi pracuję, indeks jest złożony - tzn. Ma zarówno nazwę elementu, jak i znacznik czasu, np. [email protected]|2013-05-07 05:52:51 +0200.Konwersja indeksu na MultiIndex (indeks hierarchiczny) w Pandach

Chcę wykonać hierarchiczne indeksowanie, aby te same wiadomości e-mail były pogrupowane, więc muszę przekonwertować indeks DataFrame na MultiIndex (np. Dla powyższego wpisu - ([email protected], 2013-05-07 05:52:51 +0200)).

Jaka jest najwygodniejsza metoda?

Odpowiedz

9

Gdy mamy DataFrame

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

oraz mapowanie funkcyjny każdego indeksu do krotki (poniżej, to jest na przykład z tego zapytania)

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

można utworzyć wskaźnik hierarchicznej w następujący sposób:

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

Alternatywnym podejściem jest utworzenie dwóch kolumn, a następnie ustawienie ich jako indeks (indeks oryginału zostaną odrzucone):

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']) 

lub nawet krócej

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

To był bardzo pomocny. Ale, o ile widzę, podczas wywoływania metody set_index() domyślnie jest inplace = False, więc trzeba użyć inplace = True lub też przypisać df do siebie. – Moot

+0

@Moot Dzięki, zaktualizowany. Albo literówka, albo z powrotem (4 lata temu) była domyślnie "inplace". –

+0

Świetnie! Ale były dwa miejsca - sprawdź pierwszy fragment kodu ... – Moot

2

Moje preferencje byłoby początkowo przeczytać w postaci kolumny (czyli nie jako indeksu), a następnie można użyć metody str dzielone: ​​

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 

A potem karmić to do MultiIndex (być może można to zrobić czystsze):

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

Usuń kolumnę 0TH i ustawić wskaźnik do nowego 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

W pandas>=0.16.0, możemy użyć .str akcesor na indeksach. To sprawia, że ​​następujące możliwości:

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

(Uwaga: próbowałem bardziej intuicyjny: pd.MultiIndex.from_arrays(df.index.str.split('|')) ale z jakiegoś powodu, że daje mi błędy.)

Powiązane problemy