Scala Spark DataFrame将多列聚合为一列作为字符串

Scala Spark DataFrame将多列聚合为一列作为字符串,scala,apache-spark,dataframe,dataset,Scala,Apache Spark,Dataframe,Dataset,我想将Spark数据帧转换为另一个数据帧,具体方式如下: 我有Spark数据帧: +---------+------------+ |protocol | count | +---------+------------+ | TCP| 8231 | | ICMP| 7314 | | UDP| 5523 | | IGMP| 4423 | | EGP| 2331 | +--------

我想将Spark数据帧转换为另一个数据帧,具体方式如下:

我有Spark数据帧:

+---------+------------+
|protocol |   count    |
+---------+------------+
|      TCP|    8231    |
|     ICMP|    7314    |
|      UDP|    5523    |
|     IGMP|    4423    |
|      EGP|    2331    |
+---------+------------+
我想把它变成:

+----------------------------------------------------------+
|Aggregated                                                |
+----------------------------------------------------------+
|{tcp: 8231, icmp: 7314, udp: 5523, igmp: 4423, egp: 2331} |
+----------------------------------------------------------+

聚合列可以是列表、映射或字符串。这是否可以通过DataFrame函数实现,或者我是否需要创建自己的udf来聚合此功能?

在DataFrame中添加列并创建新列:

var new_df = df.withColumn("concat", concat($"protocol", lit(" : "), $"count"))
要将其聚合为一行作为列表,可以这样做

var new_df = new_df.groupBy().agg(collect_list("concat").as("aggregated"))
new_df.show
如果希望将数据转换为字符串而不是数据帧,可以按如下方式收集数据

new_df.select("concat").collect.map(x=> x.get(0)).mkString("{", ",", "}")

在dataframe中连接列并创建新列:

var new_df = df.withColumn("concat", concat($"protocol", lit(" : "), $"count"))
要将其聚合为一行作为列表,可以这样做

var new_df = new_df.groupBy().agg(collect_list("concat").as("aggregated"))
new_df.show
如果希望将数据转换为字符串而不是数据帧,可以按如下方式收集数据

new_df.select("concat").collect.map(x=> x.get(0)).mkString("{", ",", "}")

由于您希望将所有列转换为单个列,而且开始时似乎没有多少列,因此可以
将数据帧收集到驱动程序中,并使用纯Scala代码将其转换为所需的格式

下面将为您提供一个
数组[String]

val res = df.as[(String, Int)].collect.map{case(protocol, count) => protocol + ": " + count}
要将其转换为单个字符串,只需执行以下操作:

val str = res.mkString("{", ", ", "}")

由于您希望将所有列转换为单个列,而且开始时似乎没有多少列,因此可以
将数据帧收集到驱动程序中,并使用纯Scala代码将其转换为所需的格式

下面将为您提供一个
数组[String]

val res = df.as[(String, Int)].collect.map{case(protocol, count) => protocol + ": " + count}
要将其转换为单个字符串,只需执行以下操作:

val str = res.mkString("{", ", ", "}")

pivot
toJSON
将满足您的需求

import org.apache.spark.sql.functions.first

df.groupBy().pivot("protocol").agg(first("count")).toJSON.show(false)
// +----------------------------------------------------------+                    
// |value                                                     |
// +----------------------------------------------------------+
// |{"EGP":2331,"ICMP":7314,"IGMP":4423,"TCP":8321,"UDP":5523}|
// +----------------------------------------------------------+

pivot
toJSON
将满足您的需求

import org.apache.spark.sql.functions.first

df.groupBy().pivot("protocol").agg(first("count")).toJSON.show(false)
// +----------------------------------------------------------+                    
// |value                                                     |
// +----------------------------------------------------------+
// |{"EGP":2331,"ICMP":7314,"IGMP":4423,"TCP":8321,"UDP":5523}|
// +----------------------------------------------------------+

执行此操作时是否要使用数据帧中的所有行?由于没有那么多,收集数据并使用纯Scala进行转换可能会更容易。@Shaido是的,所有的行,但给出的示例并不是唯一存在的行。行将随着时间的推移而不断增加执行此操作时是否要使用数据帧中的所有行?由于没有那么多,收集数据并使用纯Scala进行转换可能会更容易。@Shaido是的,所有的行,但给出的示例并不是唯一存在的行。随着时间的推移,行数将不断增加