迭代Spark Dataframe运行缓慢

时间:2018-05-07 22:26:23

标签: scala apache-spark spark-dataframe apache-spark-mllib google-cloud-dataproc

我想验证现有列的数据并根据特定条件创建新列。

问题:我有大约500列和9K行(9000)的数据集。根据我的逻辑,如果其中一个列具有任何空值,则创建关于该列的新列,并将原始列的空值设置为1并且休息为0.

但是下面简单的代码需要几个小时才能完成,尽管我的数据不是很大。

dataset_.schema.fields.map(c => {
  if(dataset_.filter(col(c.name).isNull).count() > 0)
  {
    dataset_ = dataset_.withColumn(c.name + "_isNull", when(col(c.name).isNull, 1).otherwise(0))
  }
})

请帮助我优化我的代码或向我提供反馈,以便通过不同的方法实现它。

注意:我在大集群(火花纱线)上尝试过相同的东西。 Google Dataproc群集(3个工作节点,机器类型32 vCPU,280 GB内存)

2 个答案:

答案 0 :(得分:0)

我尝试了很多事情......
1)尝试从dataframe文件或任何其他来源创建csv时进行缓存

2)另外,如果它不影响逻辑,我们可以尝试改变它 if(dataset_.filter(col(c.name).isNull).count() > 0)if(flightData.filter(col(x.name).isNull).take(1) != null )
我们可以检查是否有任何列名为null,而不是计算所有数据 当take(1)找到一条记录时,.count()将继续前进,而map将继续运行,然后将其与0进行比较

3)此外,根据目前的逻辑,我们可以将foreach更改为sed。但是,它不会影响性能,但理想情况下它应该是预期的。

我在有16列和大约10Lakh记录的数据集上尝试了这些。应用所有这些后花了33秒。

这是Spark UI快照! enter image description here

由于您拥有500列,因此与我的数据集相比,运行时应该大规模应用这些列 我希望这有帮助!

答案 1 :(得分:0)

同时计算所有计数:

val convert = df.select(
  df.columns.map(c => (count(c) =!= count("*")).alias(c)): _*
).first.getValuesMap[Boolean](df.columns)

并使用结果添加列

convert.collect { case (c, true) => c }.foldLeft(df) {
  (df, c) => df.withColumn(s"${c}_isNull", when(col(c).isNull, 1).otherwise(0))
}