我希望对大量数据执行大约五种不同的汇总技术。通常,我希望在某些时间范围内和其他维度上计算平均值,最小值,最大值,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
方法。
通常,我开发的管道如下所示:
partitionBy
和cat_0
进行分组,并计算先前列出的五个摘要统计信息。date_window
方法,使用pyspark.sql.window.Window
直接加入计算列。对于df.withColumn
方法,跟踪每个结果DataFrame(每列有三列:两列用于分组列,一列用于计算列)-最后,通过对分组列进行基本的归约运算来加入每个DataFrame作为键。我已经在下面留下了一些管道代码,但是主要对以下方面感兴趣:1)这些方法是否都是此类工作的“最佳实践”; 2)如果不是,我是否缺少Spark生态系统可以帮助我更快地完成这项工作/使用更少的资源吗?
当前,DataFrame.groupBy
方法的性能要好一些,但是必须跟踪每个按DataFrame分组并在最后将它们全部减少连接的麻烦。 groupBy
方法并不是很好,尽管从语法上讲它更干净,更易于维护,IMO。无论哪种情况,我都必须分配大量的计算资源才能使作业在最后运行并写入磁盘(无需重新分区/合并)。
Window