15

在我使用的数据中,索引是复合的——即它同时具有项目名称和时间戳,例如name@domain.com|2013-05-07 05:52:51 +0200.

我想做分层索引,以便将相同的电子邮件分组在一起,所以我需要将 DataFrame Index 转换为 MultiIndex(例如,对于上面的条目 - (name@domain.com, 2013-05-07 05:52:51 +0200))。

这样做最方便的方法是什么?

4

3 回答 3

23

一旦我们有了一个 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'])
于 2013-07-23T19:16:08.233 回答
9

pandas>=0.16.0中,我们可以.str在索引上使用访问器。这使得以下成为可能:

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

(注意:我尝试了更直观的方法:pd.MultiIndex.from_arrays(df.index.str.split('|'))但由于某种原因,这给了我错误。)

于 2015-12-02T00:08:20.067 回答
4

我的偏好是最初将其作为列读取(即不作为索引),然后您可以使用 str split 方法:

csv = '\n'.join(['name@domain.com|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    [name@domain.com, 2013-05-07 05:52:51 +0200]
1    [name@domain.com, 2013-05-07 05:52:51 +0200]
2    [name@domain.com, 2013-05-07 05:52:51 +0200]
Name: 0, dtype: object

然后将其输入到 MultiIndex 中(也许这可以做得更干净?):

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

删除第 0 列并将索引设置为新的 MultiIndex:

del df[0]
df.index = m

In [17]: df
Out[17]:
                                            1
name@domain.com 2013-05-07 05:52:51 +0200  42
                2013-05-07 05:52:51 +0200  42
                2013-05-07 05:52:51 +0200  42
于 2013-07-23T20:28:47.237 回答