有效地合并大量的pyspark DataFrames

时间:2019-01-17 05:55:25

标签: python dataframe pyspark apache-spark-sql

我正在尝试在Python列表中执行数千个数据帧的数据帧联合。我正在使用两种发现的方法。第一个使用for loop union,第二个使用functools.reduce。两者都适用于玩具示例,但是对于成千上万个数据帧,我正在试验严重的开销,这可能是由于JVM之外的代码导致的,每次都顺序地附加每个数据帧(使用这两种合并方法)。

<PreferenceCategory>
  <ListPreference ... />
</PreferenceCategory>

问题是如何有效地执行此多个数据帧操作,可能避免了因一对一合并数据帧而造成的开销。

非常感谢

1 个答案:

答案 0 :(得分:2)

您当前正在像这样加入您的DataFrames:

(((td1 + td2) + td3) + td4)

在每个阶段,您都在将一个大型数据帧与一个小型数据帧连接在一起,从而导致每个步骤都有一个副本,并浪费了大量内存。我建议这样合并它们:

(td1 + td2) + (td3 + td4)

这个想法是迭代合并大约相同大小的对,直到得到单个结果。这是一个原型:

def pairwise_reduce(op, x):
    while len(x) > 1:
        v = [op(i, j) for i, j in zip(x[::2], x[1::2])]
        if len(x) > 1 and len(x) % 2 == 1:
            v[-1] = op(v[-1], x[-1])
        x = v
    return x[0]

result = pairwise_reduce(DataFrame.unionAll, df_list)

您将看到这对python列表有何重大影响。

from functools import reduce 
from operator import add

x = [[1, 2, 3], [4, 5, 6], [7, 8], [9, 10, 11, 12]] * 1000

%timeit sum(x, [])
%timeit reduce(add, x)
%timeit pairwise_reduce(add, x)

64.2 ms ± 606 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
66.3 ms ± 679 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
970 µs ± 9.02 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

sum(x, []) == reduce(add, x) == pairwise_reduce(add, x)
# True