2013-07-23 3 views
9

В данных, которые я обрабатываю с индексом, является составным, то есть имеет как имя элемента, так и временную метку, например. [email protected]|2013-05-07 05:52:51 +0200.Преобразование индекса в MultiIndex (иерархический индекс) в Pandas

Я хочу выполнить иерархическую индексацию, так что одни и те же электронные письма сгруппированы вместе, поэтому мне нужно преобразовать индекс DataFrame в MultiIndex (например, для записи выше - ([email protected], 2013-05-07 05:52:51 +0200)).

Каков наиболее удобный способ для этого?

ответ

9

После того, как у нас есть DataFrame

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

и отображение функции каждого индекс к кортежу (ниже, это для примера из этого вопроса)

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

мы можем создать иерархический индекс следующим образом:

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

Альтернативный подход состоит в том, чтобы создать два столбца, а затем установить их как индекс (исходный индекс будет отброшен):

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

или еще короче

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

Это было очень полезно. Но, насколько я вижу, при вызове set_index() значение по умолчанию - inplace = False, поэтому нужно использовать inplace = True или назначить df для себя. – Moot

+0

@Moot Спасибо, обновлено. Либо опечатка, либо назад (4 года назад) она была 'inplace' по умолчанию. –

+0

Отлично! Но было два места - проверьте первый фрагмент кода ... – Moot

2

Я предпочитаю бы сначала прочитать это в качестве колонки (т.е. не в качестве индекса), то вы можете использовать метод Обл раздвоение:

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 

А потом кормить это в мультииндексных (возможно, это может быть сделано чище):

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

Удалить 0-й столбец и установить индекс к новому мультииндексных:

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

в pandas>=0.16.0, мы можем использовать .str аксессор по индексам. Это делает возможным следующее:

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

(Примечание: я попробовал более интуитивным: pd.MultiIndex.from_arrays(df.index.str.split('|')) но по какой-то причине, что дает мне ошибки.)

Смежные вопросы