首页 > 解决方案 > Spark 数据集:数据转换

问题描述

我有一个格式的 Spark 数据集 -

+--------------+--------+-----+
|name          |type    |cost |
+--------------+--------+-----+
|AAAAAAAAAAAAAA|XXXXX   |0.24|
|AAAAAAAAAAAAAA|YYYYY   |1.14|
|BBBBBBBBBBBBBB|XXXXX   |0.78|
|BBBBBBBBBBBBBB|YYYYY   |2.67|
|BBBBBBBBBBBBBB|ZZZZZ   |0.15|
|CCCCCCCCCCCCCC|XXXXX   |1.86|
|CCCCCCCCCCCCCC|YYYYY   |1.50|
|CCCCCCCCCCCCCC|ZZZZZ   |1.00|
+--------------+--------+----+

我想将其转换为类型的对象-

public class CostPerName {
    private String name;
    private Map<String, Double> costTypeMap;
}

我想要的是,

+--------------+-----------------------------------------------+
|name          |           typeCost.                           |
+--------------+-----------------------------------------------+
|AAAAAAAAAAAAAA|(XXXXX, 0.24), (YYYYY, 1.14)                   |            
|BBBBBBBBBBBBBB|(XXXXX, 0.78), (YYYYY, 2.67), (ZZZZZ, 0.15)    |
|CCCCCCCCCCCCCC|(XXXXX, 1.86), (YYYYY, 1.50), (ZZZZZ, 1.00)    |
+--------------+-----------------------------------------------+

即,对于每个name,我想要一张(type, cost).

实现这种转变的有效方法是什么?我可以使用一些数据帧转换吗?我尝试了 groupBy 但这只有在我执行 sum、avg 等聚合查询时才有效。

标签: apache-sparkapache-spark-sqlapache-spark-dataset

解决方案


您可以将两个列 type 和 cost 组合成一个新的struct列,然后按名称分组并使用collect_list作为聚合函数:

df.withColumn("type_cost", struct("type", "cost"))
     .groupBy("name").agg(collect_list("type_cost"))

这将产生一个像这样的数据框:

+--------------+---------------------------------------------+
|name          |collect_list(type_cost)                      |
+--------------+---------------------------------------------+
|AAAAAAAAAAAAAA|[[XXXXX, 0.24], [YYYYY, 1.14]]               |
|CCCCCCCCCCCCCC|[[XXXXX, 1.86], [YYYYY, 1.50], [ZZZZZ, 1.00]]|
|BBBBBBBBBBBBBB|[[XXXXX, 0.78], [YYYYY, 2.67], [ZZZZZ, 0.15]]|
+--------------+---------------------------------------------+

推荐阅读