有一个DataFrame,“rawDF”,其列是
time |id1|id2|...|avg_value|max_value|min_value|std_value|range_value|..
10/1/2015|1 |3 |...|0.0 |0.2 |null |null |null | ...
10/2/2015|2 |3 |...|null |null |0.3 |0.4 |null | ...
10/3/2015|3 |5 |...|null |null |null |0.4 |0.5 | ...
对于每一行,我想基于这五个“值”(avg,min,max,std,range)返回多行。但是,如果值为null,我想跳过。
所以,输出应该是
10/1/2015|1 |3 |...|0.0
10/1/2015|1 |3 |...|0.2
10/2/2015|2 |3 |...|0.3
10/2/2015|2 |3 |...|0.4
10/3/2015|3 |5 |...|0.4
10/3/2015|3 |5 |...|0.5
我对Scala不太熟悉,所以,我正在努力解决这个问题。
val procRDD = rawDF.flatMap( x => for(valInd <-10 to 14) yield {
if(x.get(valInd) != null) { ...)) }
} )
此代码包含null
返回。
那么,你能给我一些想法吗?
答案 0 :(得分:1)
这有点奇怪的要求,但只要您不需要有关源列的信息,并且所有值都属于同一类型,您只需explode
并删除空值:
import org.apache.spark.sql.functions.{array, explode}
val toExpand = Seq(
"avg_value", "max_value", "min_value", "std_value", "range_value"
)
// Collect *_value columns into a single Array and explode
val expanded = df.withColumn("value", explode(array(toExpand.map(col): _*)))
val result = toExpand
.foldLeft(expanded)((df, c) => df.drop(c)) // Drop obsolete columns
.na.drop(Seq("value")) // Drop rows with null value
答案 1 :(得分:0)
这是我的解决方案。如果你有更好的,请告诉我。
val procRDD = rawDF.flatMap( x =>
for(valInd <-10 to 14) yield { // valInd represents column number
if(x.get(valInd) != null) {
try { Some( ..) }
catch { case e: Exception => None}
}else None
})
.filter({case Some(y) => true; case None=> false})
.map(_.get)
实际上,我一直在寻找filter
和map
以及如何将命令放入其中。