我有一个带有两个分类列的DataFrame,类似于以下示例:
+----+-------+-------+
| ID | Cat A | Cat B |
+----+-------+-------+
| 1 | A | B |
| 2 | B | C |
| 5 | A | B |
| 7 | B | C |
| 8 | A | C |
+----+-------+-------+
我需要进行一些处理,这需要两个步骤:第一步需要按两个分类列对数据进行分组。在该示例中,它将生成以下DataFrame:
+-------+-------+-----+
| Cat A | Cat B | Cnt |
+-------+-------+-----+
| A | B | 2 |
| B | C | 2 |
| A | C | 1 |
+-------+-------+-----+
然后,下一步是仅按CatA进行分组,以计算新的聚合,例如:
+-----+-----+
| Cat | Cnt |
+-----+-----+
| A | 3 |
| B | 2 |
+-----+-----+
现在来问题:
在我的解决方案中,我通过
创建了中间数据框val df2 = df.groupBy("catA", "catB").agg(...)
然后我汇总这个df2
以获得最后一个:
val df3 = df2.groupBy("catA").agg(...)
我认为它比再次聚合第一个DF更有效。这是一个很好的假设吗?或者没有区别?
是否有任何建议可以更有效地获得相同的结果?
答案 0 :(得分:3)
一般来说,它看起来是一种好方法,应该比两次聚合数据更有效。由于shuffle文件是隐式缓存的,因此至少部分工作应该只执行一次。因此,当您在df2
上调用操作并随后在df3
上调用操作时,您应该会看到已跳过与df2
对应的阶段。第一个shuffle强制执行的部分结构也可以减少第二个agg
期间聚合缓冲区的内存需求。
不幸的是,DataFrame
聚合与RDD聚合不同,无法使用自定义分区程序。这意味着您无法使用基于值catA
的单个shuffle计算两个数据帧。这意味着第二个聚合将需要单独的交换散列分区。我怀疑是否有理由改用RDDs
。