首页 > 解决方案 > 数据框:按列名列表分组

问题描述

我有一个包含多列的数据框和一个列名列表。

我想通过根据我的列表对其进行分组来处理我的数据框。

这是我正在尝试做的一个例子:

val tagList = List("col1","col3","col5")

var tagsForGroupBy = tagList(0)

if(tagList.length>1){
     for(i <- 1 to tagList.length-1){
              tagsForGroupBy = tagsForGroupBy+","+tags(i)
     }
}

// df is a Dataframe with schema (col0, col1, col2, col3, col4, col5)
df.groupBy("col0",tagsForGroupBy)

我明白为什么它不起作用,但我不知道如何使它起作用。

最好的解决方案是什么?

编辑 :

这是我正在做的更完整的示例(包括 SCouto 解决方案):

我的 tagList 包含一些列名(“col3”、“col5”)。我还想在我的 groupBy 中包含“col0”和“col1”,与我的列表无关。在我的 groupBy 和我的聚合之后,我想从聚合中选择用于 group By 的所有列和新列。

val tagList = List("col3","col5")

val tmpListForGroup = new ListBuffer[String]()
val tmpListForSelect = new ListBuffer[String]()
tmpListForGroup +=tagList (0)
tmpListForSelect +=tagList (0)

for(i <- 1 to tagList .length-1){
    tmpListForGroup +=(tagList (i))
    tmpListForSelect +=(tagList (i))
}

tmpListForGroup +="col0"
tmpListForGroup +="col1"
tmpListForSelect +="aggValue1"
tmpListForSelect +="aggValue2"

// df is a Dataframe with schema (col0, col1, col2, col3, col4, col5)
df.groupBy(tmpListForGroup.head,tmpListForGroup.tail:_*)
  .agg(
      [aggFunction].as("aggValue1"),
      [aggFunction].as("aggValue1"))
  )
  .select(tmpListForSelect .head,tmpListForSelect .tail:_*)

这段代码完全符合我的要求,但对于(我认为)应该简单的事情来说,它看起来非常丑陋和复杂。

有另一种解决方案吗?

标签: scalaapache-sparkapache-spark-sql

解决方案


当将列名作为字符串发送时,groupBy 接收一个列作为第一个参数,并将它们的序列作为第二个参数:

def groupBy(col1: String,cols: String*)

因此,您需要发送两个参数并将第二个参数转换为序列:

这对你来说很好:

df.groupBy(tagsForGroupBy.head, tagsForGroupBy.tail:_*)

或者,如果您想将 col0 从列表中分离出来,如您的示例所示:

df.groupBy("col0", tagsForGroupBy:_*)

推荐阅读