为什么pd.concat({},axis = 1)比pd.concat({},axis = 0)慢.unstack(0)?

时间:2016-12-22 23:57:50

标签: python pandas dataframe

考虑一下这个熊猫系列词典。所有系列的索引都是整数,并且有一些潜在的重叠,但肯定不重合。当我有大量索引,大量非重叠以及许多要连接的项时,我发现pd.concataxis=1中组合时似乎很慢。它促使我离开axis=0,然后离开unstack()。我最终得到了同样的结果。但是拆散更快。

有没有人知道为什么会出现这种情况?

我认为连接系列应该很快,但我猜想卸载过程与pd.concat(axis=1)几乎完全相同。

dict_of_series = {
    's%s' % i: pd.Series(
        1, np.unique(np.random.randint(1000, 10000, size=1000))
    ) for i in range(100)
}
%%timeit
pd.concat(dict_of_series, axis=0).unstack(0)
  

10个循环,最佳3:29.6毫秒/循环

%%timeit
pd.concat(dict_of_series, axis=1)
  

10个循环,最佳3:每循环43.1 ms

1 个答案:

答案 0 :(得分:3)

快速分析显示pd.concat(dict_of_series, axis=1)消耗了pd.Index.union中的大量时间。它在内部函数_union_indexes内逐个调用每个索引 - 与我下面的函数union类似。

另一方面,pd.concat(dict_of_series, axis=0).unstack(0)使用了一些聪明的优化,我没有尝试分析。无论如何,那里没有_union_indexes甚至pd.Index.union的电话。

可以' _union_indexes'是罪魁祸首?很可能。我只拿了索引:

idxs = [d.index for d in dict_of_series.values()]

并比较了以下两个函数:

def union(idxs):
    ans = pd.Index([])
    for idx in idxs:
        ans = ans.union(idx)
    return ans

def union_multi(idxs):
    arr0 = np.concatenate(idxs)
    arr1 = np.zeros(arr0.size)
    ans = pd.MultiIndex.from_arrays([arr0, arr1])
    return ans.levels[0]

union相当于_union_indexes,而union_multi有一些多索引开销,但无法调用pd.Index.union

我粗略的时间:

>>> %timeit -n1 -r1 pd.concat(dict_of_series, axis=1)
1 loop, best of 1: 82.9 ms per loop
>>> %timeit -n1 -r1 pd.concat(dict_of_series, axis=0).unstack(0)
1 loop, best of 1: 57.9 ms per loop

>>> %timeit -n1 -r1 union(idxs)
1 loop, best of 1: 32.8 ms per loop
>>> %timeit -n1 -r1 union_multi(idxs)
1 loop, best of 1: 12.5 ms per loop

简单的pd.Index(np.unique(np.concatenate(idxs)))稍快一点,但对混合类型不起作用。

(顺便说一下,pd.concat仅在所有索引都是唯一的情况下才有效。)