我有一个数据框,并且想每次都为'a', 'b','c'
值的特定元组在一个小分区上工作。
df = pd.DataFrame({'a':np.random.randint(0,10,10000),
'b':np.random.randint(0,10,10000),
'c':np.random.randint(0,10,10000),
'value':np.random.randint(0,100,10000)})
所以我选择使用熊猫多索引:
dfi = df.set_index(['a','b','c'])
dfi.sortlevel(inplace = True)
但是,性能不是很好。
%timeit dfi.ix[(2,1,7)] # 511 us
%timeit df[(df['a'].values == 2) &
(df['b'].values == 1) & (df['c'].values == 7)] # 247 us
我怀疑某处有一些开销。我的程序有 ~1k 元组,所以一次运行需要 511 * 1000 = 0.5 秒。如何进一步改进?
更新:
嗯,我忘了提到元组的数量小于 df 中不同值'a', 'b','c'
的总笛卡尔乘积。groupby
不会对我的元组中不存在的索引做多余的工作吗?
"工作"是什么意思,但我会这样做
这几乎可以是任何功能
In [33]: %timeit df.groupby(['a','b','c']).apply(lambda x: x.sum())
10 loops, best of 3: 83.6 ms per loop
某些操作被细胞化,因此非常快
In [34]: %timeit df.groupby(['a','b','c']).sum()
100 loops, best of 3: 2.65 ms per loop
对多索引进行选择对于逐个索引执行索引效率不高。
如果你对整个组的非常小的子集进行操作,那么你可能希望直接索引到多索引中;如果你对一小部分(可能是 20%)或更多的组进行操作,则 groupby 获胜。您可能还需要调查可用于根据某些条件预筛选组filter
。
如上所述,组索引器的笛卡尔乘积无关紧要。只有实际的组才会被 groupby 迭代(将 MultiIndex 视为总可能空间的稀疏表示)。
怎么样:
dfi = df.set_index(['a','b','c'])
dfi.sortlevel(inplace = True)
value = dfi["value"].values
value[dfi.index.get_loc((2, 1, 7))]
结果是一个没有索引的 ND数组。