将自定义函数应用于spark数据帧组

时间:2016-09-20 17:17:39

标签: apache-spark dataframe group-by dataset pyspark

我有一个非常大的时间序列数据表,其中包含以下列:

  • 时间戳
  • LicensePlate
  • UberRide#
  • 速度

应考虑整组数据处理每个LicensePlate / UberRide数据集合。换句话说,我需要逐行处理数据,但所有行都按(LicensePlate / UberRide)分组。

我打算在数据帧api中使用spark,但我对如何在spark分组数据帧上执行自定义计算感到困惑。

我需要做的是:

  1. 获取所有数据
  2. 按专栏分组
  3. Foreach spark数据帧组应用f(x)。返回自定义对象foreach组
  4. 通过应用g(x)并返回单个自定义对象来获取结果
  5. 如何执行第3步和第4步?我应该使用哪些关于spark API(数据帧,数据集,rdd,也许是pandas ......)的提示?

    整个工作流程如下所示:

    Workflow

2 个答案:

答案 0 :(得分:7)

  • 虽然Spark提供了一些与Pandas集成的方法,但它并没有让Pandas分发。因此无论你在Spark中使用Pandas做什么都只是本地的(在转换中使用时是驱动程序或执行程序)操作。

    如果您正在寻找具有类似Pandas API的分布式系统,您应该查看dask

  • You can define User Defined Aggregate functions or Aggregators处理已分组的Datasets,但API的这一部分只能在Scala中直接访问。创建一个write a Python wrapper并不难。
  • RDD API提供了许多功能,可用于以低级repartition / repartitionAndSortWithinPartitions开头并以多种*byKey方法结束的组中执行操作( combineByKeygroupByKeyreduceByKey等。)

    哪一个适用于你的情况取决于你想要应用的函数的属性(它是关联的和可交换的,它可以在流上工作,它是否期望特定的顺序)。

    最普遍但效率最低的方法可归纳如下:

    h(rdd.keyBy(f).groupByKey().mapValues(g).collect())
    

    其中f从值映射到keyg对应于每组聚合,h是最终合并。大部分时间你都可以做得更好,所以它应该只作为最后的手段使用。

  • 使用DataFrames / Spark SQL和window functions可以表达相对复杂的逻辑。

  • 另请参阅Applying UDFs on GroupedData in PySpark (with functioning python example)

答案 1 :(得分:6)

自Spark 2.3以来,您正在寻找的是:Pandas矢量化UDF。它允许对DataFrame进行分组并对大熊猫应用自定义转换,分布在每个组中:

 Error: `.funs` must contain one renaming function, not 4 

这很容易使用,所以我只想放a link to Databricks' presentation of pandas UDF

但是,我不知道在Scala中进行分组转换的实用方法,所以欢迎任何其他建议。

编辑:在Scala中,您可以使用数据集的df.groupBy("groupColumn").apply(myCustomPandasTransformation) + groupByKey / mapGroups来实现自早期版本Spark以来的相同功能。