快速分析表明,pd.Index.union会消耗pd.concat(dict_of_series,axis = 1)调用中的大量时间.它在内部函数_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才有效.)