将RDD转换为DataFrame时导致重新分区的原因是什么?

时间:2017-06-13 06:25:26

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

我使用Window.sum函数来获取RDD中值的总和,但是当我将DataFrame转换为RDD时,我发现结果只有一个分区。何时进行重新分区?

 val rdd = sc.parallelize(List(1,3,2,4,5,6,7,8), 4)
    val df = rdd.toDF("values").
        withColumn("csum", sum(col("values")).over(Window.orderBy("values")))
    df.show()
    println(s"numPartitions ${df.rdd.getNumPartitions}")
    // 1
    //df is:
//    +------+----+
//    |values|csum|
//    +------+----+
//    |     1|   1|
//    |     2|   3|
//    |     3|   6|
//    |     4|  10|
//    |     5|  15|
//    |     6|  21|
//    |     7|  28|
//    |     8|  36|
//    +------+----+

我在Window中添加了partitionBy,但结果是错误,我该怎么办?这是我的更改代码:

     val rdd=sc.parallelize(List(1,3,2,4,5,6,7,8),4)
        val sqlContext = new SQLContext(m_sparkCtx)
        import sqlContext.implicits._
        val df = rdd.toDF("values").withColumn("csum", sum(col("values")).over(Window.partitionBy("values").orderBy("values")))
        df.show()
        println(s"numPartitions ${df.rdd.getNumPartitions}")
       //1
//df is:
//    +------+----+
//    |values|csum|
//    +------+----+
//    |     1|   1|
//    |     6|   6|
//    |     3|   3|
//    |     5|   5|
//    |     4|   4|
//    |     8|   8|
//    |     7|   7|
//    |     2|   2|
//    +------+----+

1 个答案:

答案 0 :(得分:1)

Window函数有partitionBy个API,用于对dataframeorderBy进行分组,以按升序或降序对分组的rows进行排序。

在您的第一个案例中,您尚未定义partitionBy,因此所有值都被归为一个dataframe以进行排序,从而将数据混合到一个分区中。

但在第二种情况下,您partitionBy本身已定义values。因此,由于每个值都是不同的,因此每个row被分组为单独的组。

第二种情况下的partition为200,因为当您没有定义分区并发生随机播放时,这是spark中定义的默认分区

要在第一种情况下获得相同的结果,您需要添加另一个column分组值,以便您可以将它们分组为第一种情况,即分组到一组。

val rdd=sc.parallelize(List(1,3,2,4,5,6,7,8),4)
val df = rdd.toDF("values").withColumn("grouping", lit("group"))
  df.withColumn("csum", sum(col("values")).over(Window.partitionBy("grouping").orderBy("values"))).drop("grouping").show(false)

通过执行此操作,我看到您的原始分区已保留。