在Apache Spark中删除空的DataFrame分区

时间:2017-01-25 15:08:58

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

我尝试根据DataFrame在分区列(ListView) view.findViewById(android.R.id.list); 中具有N(假设为N=3)不同值的列重新分区DataFrame,例如:

x

我想要实现的是val myDF = sc.parallelize(Seq(1,1,2,2,3,3)).toDF("x") // create dummy data 重新分配myDF而不产生空分区。有没有比这样做更好的方法?

x

(如果我没有在val numParts = myDF.select($"x").distinct().count.toInt myDF.repartition(numParts,$"x") 中指定numParts,我的大多数分区都是空的(因为repartiton创建了200个分区)...)

1 个答案:

答案 0 :(得分:5)

我想到迭代df分区并在其中获取记录数来找到非空分区的解决方案。

val nonEmptyPart = sparkContext.longAccumulator("nonEmptyPart") 

df.foreachPartition(partition =>
  if (partition.length > 0) nonEmptyPart.add(1))

由于我们得到了非空分区(nonEmptyPart),我们可以使用coalesce()check coalesce() vs reparation())来清空空分区。

val finalDf = df.coalesce(nonEmptyPart.value.toInt) //coalesce() accepts only Int type

它可能是也可能不是最好的,但是这个解决方案会避免改组,因为我们没有使用reparation()

解决评论的示例

val df1 = sc.parallelize(Seq(1, 1, 2, 2, 3, 3)).toDF("x").repartition($"x")
val nonEmptyPart = sc.longAccumulator("nonEmptyPart")

df1.foreachPartition(partition =>
  if (partition.length > 0) nonEmptyPart.add(1))

val finalDf = df1.coalesce(nonEmptyPart.value.toInt)

println(s"nonEmptyPart => ${nonEmptyPart.value.toInt}")
println(s"df.rdd.partitions.length => ${df1.rdd.partitions.length}")
println(s"finalDf.rdd.partitions.length => ${finalDf.rdd.partitions.length}")

<强>输出

nonEmptyPart => 3
df.rdd.partitions.length => 200
finalDf.rdd.partitions.length => 3