在Pyspark/Python中使用不同的值组合多行

在Pyspark/Python中使用不同的值组合多行,python,apache-spark,pyspark,apache-spark-sql,pyspark-dataframes,Python,Apache Spark,Pyspark,Apache Spark Sql,Pyspark Dataframes,我有一张如下表: ID Date Class Level 1 2021/01/01 math 1 1 2021/01/01 english 1 1 2021/01/01 history 1 ID Date Class Level 1 2021/01/01 english,history,math 1 我现在的代码是 grouped_df

我有一张如下表:

ID Date         Class     Level
1  2021/01/01    math      1
1  2021/01/01    english   1
1  2021/01/01    history   1
  ID Date        Class                       Level
  1  2021/01/01  english,history,math        1
我现在的代码是

    grouped_df = df\
    .groupby('ID','Date')\
    .agg(collect_list('class').alias("class"),collect_list('level').alias("level"))\
    .withColumn("class", concat_ws(", ", "class"))\
    .withColumn("level", concat_ws(", ", "level"))
代码给我的输出如下所示:

    ID Date         Class                       Level
    1  2021/01/01    math, english,history      1, 1, 1
因为我想对合并行进行排序,所以我使用了
concat_ws
,但是类的顺序不是按需求排序的,在执行
concat_ws()
时有什么方法对其进行排序吗?我想结合
按字母顺序排序。比如英语、历史、数学。但是当我做concat时,输出可以是
math\u english,history,
history,math,english

是否有一种方法可以使输出如下所示:

ID Date         Class     Level
1  2021/01/01    math      1
1  2021/01/01    english   1
1  2021/01/01    history   1
  ID Date        Class                       Level
  1  2021/01/01  english,history,math        1

您可以使用
collect\u set
删除重复项:

grouped_df = df\
    .groupby('ID','Date')\
    .agg(collect_list('class').alias("class"),collect_set('level').alias("level"))\
    .withColumn("class", concat_ws(", ", "class"))\
    .withColumn("level", concat_ws(", ", "level"))

如果总是只有一个级别,也可以考虑按级别分组,例如

grouped_df = df\
    .groupby('ID','Date', 'level')\
    .agg(collect_list('class').alias("class"))\
    .withColumn("class", concat_ws(", ", "class"))
编辑:如果要对数组进行排序,可以使用
sort\u array

grouped_df = df\
    .groupby('ID','Date')\
    .agg(sort_array(collect_list('class')).alias("class"),collect_set('level').alias("level"))\
    .withColumn("class", concat_ws(", ", "class"))\
    .withColumn("level", concat_ws(", ", "level"))

要获取
级别的唯一值
请使用
收集集
并对
值进行排序,您不能在Spark 2.3中使用
数组排序
,但您可以在排序窗口上使用
收集列表
来获取排序列表,而不是使用通常会导致性能不佳的UDF:

from pyspark.sql import Window
from pyspark.sql import functions as F


w = Window.partitionBy("ID", "Date").orderBy("Class")

grouped_df = df.withColumn("Class", F.collect_list("Class").over(w)) \
    .withColumn("Level", F.collect_set("Level").over(w)) \
    .groupBy("ID", "Date") \
    .agg(
    F.concat_ws(",", F.max("Class")).alias("Class"),
    F.concat_ws(",", F.max("Level")).alias("Level")
)

grouped_df.show(truncate=False)

# +---+----------+--------------------+-----+
# |ID |Date      |Class               |Level|
# +---+----------+--------------------+-----+
# |1  |2021/01/01|english,history,math|1    |
# +---+----------+--------------------+-----+

在执行concat_ws时,合并的行没有排序,有没有办法对其排序?例如,我的联合收割机行希望按字母顺序排列sort@yokielove您可以使用
array\u sort
我有一个错误:NameError:name'array\u sort'未定义,是否需要添加任何导入?我已经进口了array@yokielove您可以
从pyspark.sql.functions导入数组\u排序
在我这方面也不起作用,我有一个错误:ImportError:无法导入名称“数组\u排序”