我想根据索引为我的数据框创建一个子索引。例如,我有一个这样的数据框:
Content Date
ID
Bob birthday 2010.03.01
Bob school 2010.04.01
Tom shopping 2010.02.01
Tom work 2010.09.01
Tom holiday 2010.10.01
我想为我的ID
创建子索引,结果数据框如下所示:
Content Date
ID subindex
Bob 1 birthday 2010.03.01
2 school 2010.04.01
Tom 1 shopping 2010.02.01
2 work 2010.09.01
3 holiday 2010.10.01
要做到这一点,我需要先创建我的subindex
列表。我在帮助文档中搜索,似乎最简洁的方法是使用transform
:
subindex = df['Date'].groupby(df.index).transform(lambda x: np.arange(1, len(x) + 1))
然而,它真的很慢。我环顾四周,发现apply
也可以做这项工作:
subindex = df['Date'].groupby(df.index).apply(lambda x: np.arange(1, len(x) + 1))
当然subindex
需要展平,因为这是列表。这比transform
方法快得多。然后我用我自己的for loop
进行了测试:
subindex_size = df.groupby(df.index, sort = False).size()
subindex = []
for i in np.arange(len(subindex_size)):
subindex.extend(np.arange(1,subindex_size[i]+1))
它甚至更快。使用我更大的数据集(大约90k行),transform
方法在我的计算机上大约需要44秒,apply
大约需要2秒,而for loop
只需要大约1秒。我需要处理更大的数据集,因此即使apply
和for loop
之间的时差也会对我产生影响。但是,for loop
看起来很丑,如果我需要创建其他基于组的变量,可能不会轻易应用。
所以我的问题是,为什么应该做正确事情的内置函数更慢?我在这里遗漏了什么或者有什么理由吗?有没有其他方法可以改善这个过程?
答案 0 :(得分:3)
您可以使用cumcount执行此操作:
In [11]: df.groupby(level=0).cumcount()
Out[11]:
ID
Bob 0
Bob 1
Tom 0
Tom 1
Tom 2
dtype: int64
In [12]: df['subindex'] = df.groupby(level=0).cumcount() # possibly + 1 here.
In [13]: df.set_index('subindex', append=True)
Out[13]:
Content Date
ID subindex
Bob 0 birthday 2010.03.01
1 school 2010.04.01
Tom 0 shopping 2010.02.01
1 work 2010.09.01
2 holiday 2010.10.01
要从1开始(而不是0),只需在cumcount的结果中加1。