我有大约20-25个来自conf文件的列列表,并且必须聚合第一个Notnull值。我尝试使用函数传递列表和agg expr来读取conf文件。
我能够获得第一个功能,但无法找到如何首先指定ignoreNull
值为真。
我尝试的代码是
def groupAndAggregate(df: DataFrame, cols: List[String] , aggregateFun: Map[String, String]): DataFrame = {
df.groupBy(cols.head, cols.tail: _*).agg(aggregateFun)
}
val df = sc.parallelize(Seq(
(0, null, "1"),
(1, "2", "2"),
(0, "3", "3"),
(0, "4", "4"),
(1, "5", "5"),
(1, "6", "6"),
(1, "7", "7")
)).toDF("grp", "col1", "col2")
//first
groupAndAggregate(df, List("grp"), Map("col1"-> "first", "col2"-> "COUNT") ).show()
+---+-----------+-----------+
|grp|first(col1)|count(col2)|
+---+-----------+-----------+
| 1| 2| 4|
| 0| | 3|
+---+-----------+-----------+
我需要得到3作为结果而不是null。 我使用的是Spark 2.1.0和Scala 2.11
编辑1:
如果我使用以下功能
import org.apache.spark.sql.functions.{first,count}
df.groupBy("grp").agg(first(df("col1"), ignoreNulls = true), count("col2")).show()
我得到了我想要的结果。我们可以在地图中传递ignoreNulls
true
作为第一个函数吗?
答案 0 :(得分:1)
我已经能够通过创建列列表并将其传递给groupBy的agg函数来实现此目的。早期的方法有一个问题,我无法命名列,因为agg函数没有返回输出DF中列的顺序,我已经重命名列表中的列。
import org.apache.spark.sql.functions._
def groupAndAggregate(df: DataFrame): DataFrame = {
val list: ListBuffer[Column] = new ListBuffer[Column]()
try {
val columnFound = getAggColumns(df) // function to return a Map[String, String]
val agg_func = columnFound.entrySet().toList.
foreach(field =>
list += first(df(columnFound.getOrDefault(field.getKey, "")),ignoreNulls = true).as(field.getKey)
)
list += sum(df("col1")).as("watch_time")
list += count("*").as("frequency")
val groupColumns = getGroupColumns(df) // function to return a List[String]
val output = df.groupBy(groupColumns.head, groupColumns.tail: _*).agg(
list.head, list.tail: _*
)
output
} catch {
case e: Exception => {
e.printStackTrace()}
null
}
}
答案 1 :(得分:0)