Spark DataFame聚合:Windows +分区与groupBy操作

时间:2018-09-25 01:03:04

标签: python apache-spark dataframe

我希望对大量数据执行大约五种不同的汇总技术。通常,我希望在某些时间范围内和其他维度上计算平均值,最小值,最大值,stddev和总和。

这里有一个我可以做的例子:

import random
import string
import datetime

from pyspark.sql import SparkSession, functions as func
from pyspark.conf import SparkConf
from pyspark.sql.types import StringType, DoubleType, IntegerType
from pyspark.sql.window import Window

########## Setting up DataFrame ##########
def random_date(start, n):
    current = start
    for _ in range(n):
        current = current + datetime.timedelta(seconds=random.randrange(60))
        yield current

start_date = datetime.datetime(2013, 9, 20, 13, 00)

n_records = 50000000

dates = list(random_date(start_date, n_records))

other_data = []
for d in dates:
    categorical_data = tuple(random.choice(string.ascii_lowercase) for _ in range(1))
    numerical_data = tuple(random.randrange(100) for _ in range(20))
    other_data.append(categorical_data + numerical_data + (d,))

categorical_columns = ['cat_{}'.format(n) for n in range(1)]
numerical_columns = ['num_{}'.format(n) for n in range(20)]
date_column = ['date']

columns = categorical_columns + numerical_columns + date_column

df = sc.parallelize(other_data).toDF(columns)

df = df.withColumn('date_window', func.window('date', '5 minutes'))

df.registerTempTable('df')

########## End DataFrame setup ##########

到目前为止,我已经尝试了两种技术:一种使用内置的DataFrame.groupBy机制。另一个使用pyspark.sql.window.Window的{​​{1}}和orderBy方法。

通常,我开发的管道如下所示:

  1. 对于每个数字列,将分类列partitionBycat_0进行分组,并计算先前列出的五个摘要统计信息。
  2. 对于date_window方法,使用pyspark.sql.window.Window直接加入计算列。对于df.withColumn方法,跟踪每个结果DataFrame(每列有三列:两列用于分组列,一列用于计算列)-最后,通过对分组列进行基本的归约运算来加入每个DataFrame作为键。

我已经在下面留下了一些管道代码,但是主要对以下方面感兴趣:1)这些方法是否都是此类工作的“最佳实践”; 2)如果不是,我是否缺少Spark生态系统可以帮助我更快地完成这项工作/使用更少的资源吗?

当前,DataFrame.groupBy方法的性能要好一些,但是必须跟踪每个按DataFrame分组并在最后将它们全部减少连接的麻烦。 groupBy方法并不是很好,尽管从语法上讲它更干净,更易于维护,IMO。无论哪种情况,我都必须分配大量的计算资源才能使作业在最后运行并写入磁盘(无需重新分区/合并)。

Window

0 个答案:

没有答案