Scala Spark:groupBy并将分组数据视为数据集
我有一个Spark数据集,我想对数据进行分组并处理这些组,每个组产生零个或一个元素。比如:Scala Spark:groupBy并将分组数据视为数据集,scala,apache-spark,apache-spark-sql,Scala,Apache Spark,Apache Spark Sql,我有一个Spark数据集,我想对数据进行分组并处理这些组,每个组产生零个或一个元素。比如: val resulDataset = inputDataset .groupBy('x, 'y) .flatMap(...) 我没有找到在groupBy之后应用函数的方法,但似乎我可以使用groupByKey来代替(这是个好主意吗?有更好的方法吗?) 这是可行的,但有一件事:我希望将这些组作为Datasets进行处理。原因是我已经在数据集上使用了方便的函数,并且希望在计算每个组的结果时重用它们。
val resulDataset = inputDataset
.groupBy('x, 'y)
.flatMap(...)
我没有找到在groupBy
之后应用函数的方法,但似乎我可以使用groupByKey
来代替(这是个好主意吗?有更好的方法吗?)
这是可行的,但有一件事:我希望将这些组作为
Dataset
s进行处理。原因是我已经在数据集上使用了方便的函数,并且希望在计算每个组的结果时重用它们。但是,groupByKey.flatMap
在分组元素上生成一个迭代器,而不是数据集
问题:Spark中是否有方法将输入数据集分组并将自定义函数映射到每个组,同时将分组的元素视为数据集?例如:
val inputDataset: Dataset[T] = ...
val resulDataset: Dataset[U] = inputDataset
.groupBy(...)
.flatMap(group: Dataset[T] => {
// using Dataset API to calculate resulting value, e.g.:
group.withColumn(row_number().over(...))....as[U]
})
请注意,分组数据是有界的,可以在单个节点上处理它。但是组的数量可能非常高,因此需要分发生成的数据集。使用Dataset API来处理组纯粹是使用方便的API的问题
到目前为止,我尝试的是:
- 从映射函数中的迭代器创建数据集-从SparkSession创建NPE失败(我的理解是,这归结为无法在处理数据集的函数中创建数据集;请参阅和)
- 尝试克服第一个解决方案中的问题,尝试创建新SparkSession以在新会话中创建数据集;使用SparkSession.newSession中的NPE失败
- (ab)使用
重新分区('x,'y).mapPartitions(…)
,但这也会为每个分区生成一个迭代器[T]
,而不是一个数据集[T]
- 最后,(ab)使用
filter
:我可以将分组条件的所有不同值收集到一个数组中(select.distinct.collect
),并迭代该数组以过滤源数据集,为每个组生成一个数据集(类似于本文的想法);虽然这是可行的,但我的理解是,它收集单个节点上的所有数据,因此无法扩展,最终会出现内存问题
“我已经在数据集上使用了方便的函数”,您能告诉我您想在groupeddata上使用哪些函数吗?此外,如果可能的话,您能否提供示例输入和预期输出以及您打算重用的函数,以帮助解决您的问题。谢谢。下面是几个我想要重用的函数的例子。有些来自我的库,例如数据集上的线性插值(在其实现中广泛使用窗口函数)。从这一步开始,代码可以在技术上进行重构,以使用window.partitionBy
并重用其余部分。其他的是一个数据集API本身,特别是我需要用来计算百分位数的Dataset.summary
函数。从这次开始,API似乎只允许在整个数据集上应用此操作,而我需要在每个组上分别应用此操作。“我已经在数据集上使用了方便的函数”,您能告诉我您希望在groupeddata上使用哪些函数吗?此外,如果可能的话,您能否提供示例输入和预期输出以及您打算重用的函数,以帮助解决您的问题。谢谢。下面是几个我想要重用的函数的例子。有些来自我的库,例如数据集上的线性插值(在其实现中广泛使用窗口函数)。从这一步开始,代码可以在技术上进行重构,以使用window.partitionBy
并重用其余部分。其他的是一个数据集API本身,特别是我需要用来计算百分位数的Dataset.summary
函数。到目前为止,API似乎只允许对整个数据集应用此操作,而我需要对每个组分别应用此操作。
val inputDataset: Dataset[T] = ...
val resulDataset: Dataset[U] = inputDataset
.groupBy(...)
.flatMap(group: Dataset[T] => {
// using Dataset API to calculate resulting value, e.g.:
group.withColumn(row_number().over(...))....as[U]
})