Spark - 在groupby和collect过程中,保持各列数据的顺序。

问题描述 投票:0回答:1

如果我有

ID  Name     Code    Value
1   Person1  A       12
1   Person2  B       15

而我做了一个

df.groupBy("ID").agg(
collect_set("Name").alias("Name"),
collect_set("Code").alias("Code"),
collect_set("Value").alias("Value")
)

我可能会得到一个

1, [Person1, Person2], [B,A], [15,12]

我需要得到一个

1, [Person1, Person2], [A,B], [12,15]

我如何确保所有列的顺序相同?

我的实际DF有70列,我需要按一列进行分组,并按照正确的顺序为每列挑选前5个唯一的值。

如有任何建议,深表感谢

scala apache-spark hadoop bigdata
1个回答
2
投票

你不能确定你的集合的顺序,我建议把属性打包在一个结构中,这样你会得到一个数组而不是3个。

df.groupBy("ID").agg(
  collect_list(struct("Name","Code","Value").as("Attribute")).as("Attributes")
)

0
投票

集合不保留顺序。但是你可以在对数组进行 collect_list 借用 satellite data.

你可以在前面加上 Person 名称的属性,如下图所示。

val df2 = df.map(each => {
      val person = each.getString(1)
     (each.getInt(0), person + "|" + each.getString(1), person + "|" + each.getString(2), person + "|" + each.getInt(3))
     }).toDF("ID","Name","Code","Value")

现在,你可以使用 sort_array 之后 collect_list,它将会对所有属性进行排序,按照 Name 的人

val df3 = df2.groupBy("ID").agg( 
sort_array(collect_set("Name")).alias("Name"),
sort_array(collect_set("Code")).alias("Code"),
sort_array(collect_set("Value")).alias("Value"))

请注意,每个属性都在结果列表中附加了人的信息。

df3.show
+---+--------------------+--------------------+--------------------+
| ID|                Name|                Code|               Value|
+---+--------------------+--------------------+--------------------+
|  1|[Person1|Person1,...|[Person1|A, Perso...|[Person1|12, Pers...|
+---+--------------------+--------------------+--------------------+
© www.soinside.com 2019 - 2024. All rights reserved.