我想验证现有列的数据并根据特定条件创建新列。
问题:我有大约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内存)
答案 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秒。
由于您拥有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))
}