在并行Scala中处理多个数据帧

时间:2020-07-17 12:00:56

标签: scala apache-spark parallel-processing apache-spark-sql

我是Scala-Spark的新手。我有一个像下面这样的数据框,我需要根据一个组ID将其分成不同的数据块,并并行地对其进行独立处理。

+----+-------+-----+-------+
|user|feature|value|groupID
+----+-------+-----+-------+
|   1|    100|    1|      A|
|   2|    20B|    0|      B|
|   3|    30A|    1|      B|
|   4|    40A|    1|      B| 
|   5|    50A|    1|      A|
|   6|    10A|    0|      B|
|   7|    200|    1|      A|
|   8|    30B|    1|      B|
|   9|    400|    0|      A|
|  10|    50C|    0|      A|
+----+-------+-----+-------+

1步,我需要将其拆分为两个不同的df,如下所示:我可以为此使用过滤器。但是我不确定是否(由于它们将产生大量不同的数据帧)我应该将它们作为拼花形式保存到ADLS中还是将其保存在内存中。

+----+-------+-----+-------+
|user|feature|value|groupID
+----+-------+-----+-------+
|   1|    100|    1|      A|
|   5|    50A|    1|      A|
|   7|    200|    1|      A|
|   9|    400|    0|      A|
|  10|    50C|    0|      A|
+----+-------+-----+-------+

+----+-------+-----+-------+
|user|feature|value|groupID
+----+-------+-----+-------+
|   2|    20B|    0|      B|
|   3|    30A|    1|      B|
|   4|    40A|    1|      B| 
|   6|    10A|    0|      B|
|   8|    30B|    1|      B|
+----+-------+-----+-------+

2步骤以并行方式独立处理每个数据框,并获得独立处理的数据框。

提供一些背景信息:

  • groupId的数量很大,因此无法进行硬编码。

  • 每个数据帧的处理最好并行进行。

我希望就如何进行一个简短的想法:我已经看过.par.foreach(但是我不清楚如何将其应用于动态数量的数据帧以及如何独立存储它们,或者是否是最有效的方法)

1 个答案:

答案 0 :(得分:0)

检查以下代码。

scala> df.show(false)
+----+-------+-----+-------+
|user|feature|value|groupID|
+----+-------+-----+-------+
|1   |100    |1    |A      |
|2   |20B    |0    |B      |
|3   |30A    |1    |B      |
|4   |40A    |1    |B      |
|5   |50A    |1    |A      |
|6   |10A    |0    |B      |
|7   |200    |1    |A      |
|8   |30B    |1    |B      |
|9   |400    |0    |A      |
|10  |50C    |0    |A      |
+----+-------+-----+-------+

从数据框中获取distinct个groupid值。

scala> val groupIds = df.select($"groupID").distinct.as[String].collect // Get distinct group ids.
groupIds: Array[String] = Array(B, A)

使用.par进行并行处理。您需要在map内添加逻辑。

scala> groupIds.par.map(groupid => df.filter($"groupId" === lit(groupid))).foreach(_.show(false)) // here you might need add your logic to save or any other inside map function not foreach.., for example I have added logic to show dataframe content in foreach.
+----+-------+-----+-------+
|user|feature|value|groupID|
+----+-------+-----+-------+
|2   |20B    |0    |B      |
|3   |30A    |1    |B      |
|4   |40A    |1    |B      |
|6   |10A    |0    |B      |
|8   |30B    |1    |B      |
+----+-------+-----+-------+

+----+-------+-----+-------+
|user|feature|value|groupID|
+----+-------+-----+-------+
|1   |100    |1    |A      |
|5   |50A    |1    |A      |
|7   |200    |1    |A      |
|9   |400    |0    |A      |
|10  |50C    |0    |A      |
+----+-------+-----+-------+