以下代码可用于过滤包含值为1的行。图像中有很多列。
import org.apache.spark.sql.types.StructType
val df = sc.parallelize(Seq(
("r1", 1, 1),
("r2", 6, 4),
("r3", 4, 1),
("r4", 1, 2)
)).toDF("ID", "a", "b")
val ones = df.schema.map(c => c.name).drop(1).map(x => when(col(x) === 1, 1).otherwise(0)).reduce(_ + _)
df.withColumn("ones", ones).where($"ones" === 0).show
这里的缺点是,理想情况下,当满足第一个此类条件时,它应该停止。即找到的第一列。好,我们都知道。
但是,如果不使用UDF或非常特定的逻辑,我将找不到一种完美的方法来实现这一目标。地图将处理所有列。
因此可以使用可以在首次发现可能出现时终止的fold(Left)吗?还是其他方法?可能是疏忽。
答案 0 :(得分:1)
我的第一个想法是使用逻辑表达式并希望发生短路,但似乎火花没有这样做:
df
.withColumn("ones", df.columns.tail.map(x => when(col(x) === 1, true).otherwise(false)).reduceLeft(_ or _))
.where(!$"ones")
.show()
但是我不确定火花是否支持短路,我认为不支持(https://issues.apache.org/jira/browse/SPARK-18712)
因此,您也可以在scala的exist
上使用懒惰的Seq
在行上应用自定义函数:
df
.map{r => (r.getString(0),r.toSeq.tail.exists(c => c.asInstanceOf[Int]==1))}
.toDF("ID","ones")
.show()
此方法类似于UDF,因此不确定是否可以接受。