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

时间:2018-05-17 08:19:43

标签: scala apache-spark dataframe dataset

我想以特定的方式将Spark DataFrame转换为另一个DataFrame,如下所示:

我有Spark DataFrame:

+---------+------------+
|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来聚合它?

3 个答案:

答案 0 :(得分:2)

pivottoJSON将为您提供所需

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}|
// +----------------------------------------------------------+

答案 1 :(得分:0)

数据框中的Concat列并创建一个新列:

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("{", ",", "}")

答案 2 :(得分:0)

由于您希望将所有列转换为单个列,并且它似乎不是很多列,您可以collect将数据帧Array[String]添加到驱动程序并使用纯Scala代码将其转换为格式你想要的。

以下内容将为您提供val res = df.as[(String, Int)].collect.map{case(protocol, count) => protocol + ": " + count}

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

要将其转换为单个字符串,只需执行以下操作:

def repeat_function(n, function, input_number):
    for i in range(n):
        input_number = function(input_number)
    return input_number

def times_three(x):
    return x * 3

print(repeat_function(3, times_three, 10))  #prints 270 so it's correct
print(times_three(times_three(times_three(10))))  #prints 270 so it's correct

#This function does not work
def new_repeat_function(n, function):
    result = lambda x : function(x)
    for i in range(n-1):
        result = lambda x : function(result(x))
    return result

new_function = new_repeat_function(3, times_three)
#I want new_function = lambda x : times_three(times_three(times_three(x))) 
print(new_function(10)) # should return 270 but does not work