Spark:分组数据上的“计数”是转换还是动作?

时间:2018-10-24 10:10:27

标签: scala apache-spark

我知道在RDD或DataFrame上调用的count是一个动作。但是在摆弄火花壳时,我观察到以下情况

scala> val empDF = Seq((1,"James Gordon", 30, "Homicide"),(2,"Harvey Bullock", 35, "Homicide"),(3,"Kristen Kringle", 28, "Records"),(4,"Edward Nygma", 30, "Forensics"),(5,"Leslie Thompkins", 31, "Forensics")).toDF("id", "name", "age", "department")
empDF: org.apache.spark.sql.DataFrame = [id: int, name: string, age: int, department: string]

scala> empDF.show
+---+----------------+---+----------+
| id|            name|age|department|
+---+----------------+---+----------+
|  1|    James Gordon| 30|  Homicide|
|  2|  Harvey Bullock| 35|  Homicide|
|  3| Kristen Kringle| 28|   Records|
|  4|    Edward Nygma| 30| Forensics|
|  5|Leslie Thompkins| 31| Forensics|
+---+----------------+---+----------+

scala> empDF.groupBy("department").count //count returned a DataFrame
res1: org.apache.spark.sql.DataFrame = [department: string, count: bigint]

scala> res1.show
+----------+-----+                                                              
|department|count|
+----------+-----+
|  Homicide|    2|
|   Records|    1|
| Forensics|    2|
+----------+-----+

当我在GroupedData(count)上调用empDF.groupBy("department")时,得到了另一个DataFrame作为结果(res1)。这使我相信count在这种情况下是一种转换。进一步支持以下事实:当我调用count时没有触发任何计算,而是在我运行res1.show时开始计算。

我还找不到任何文档,表明count也可能是一种转换。有人可以帮忙澄清一下吗?

3 个答案:

答案 0 :(得分:5)

您在代码中使用的.count()已超过RelationalGroupedDataset,这将创建一个新列,其中包含分组数据集中的元素数。这是转化。参考: https://spark.apache.org/docs/1.6.0/api/scala/index.html#org.apache.spark.sql.GroupedDataset

您通常在.count()上使用的RDD/DataFrame/Dataset与上面的完全不同,并且此.count() Action 。请参阅:https://spark.apache.org/docs/1.6.0/api/scala/index.html#org.apache.spark.rdd.RDD

编辑:

在对groupedDataSet进行操作时,始终将.count().agg()一起使用,以避免将来造成混淆:

empDF.groupBy($"department").agg(count($"department") as "countDepartment").show

答案 1 :(得分:1)

您已经知道-如果方法返回分布式对象(DatasetRDD),则可以将其视为转换。

但是,这些区别比数据集更适合于RDD。后者具有优化器,包括最近添加的基于成本的优化器,并且可能不像以前的API那么懒,在某些情况下模糊了转换和操作之间的差异。

在这里可以肯定地说count是一种转换。

答案 2 :(得分:0)

案例1:

您使用rdd.count()来计算行数。由于它启动DAG执行并将数据返回给驱动程序,因此它是RDD的动作

例如:rdd.count // it returns a Long value

案例2:

如果在Dataframe上调用count,它将启动DAG执行并将数据返回给驱动程序,这是Dataframe的操作

例如:df.count // it returns a Long value

案例3:

在您的情况下,您要在groupBy上调用dataframe并返回RelationalGroupedDataset对象,而您要在分组数据集上调用count并返回Dataframe,因此它是转换,因为它不会将数据获取到驱动程序并启动DAG执行。

例如:

 df.groupBy("department") // returns RelationalGroupedDataset
          .count // returns a Dataframe so a transformation
          .count // returns a Long value since called on DF so an action