Pyspark-groupby按顺序对字符串列进行concat

Pyspark-groupby按顺序对字符串列进行concat,pyspark,Pyspark,我有一个包含以下列的数据框-用户、订单、食物 例如: df = spark.createDataFrame(pd.DataFrame([['A','B','A','C','A'],[1,1,2,1,3],['Eggs','Salad','Peaches','Bread','Water']],index=['User','Order','Food']).T) 我想把所有的食物连接成一个字符串,按顺序排序,按用户分组 如果我运行以下命令: df.groupBy("User").agg(concat

我有一个包含以下列的数据框-用户、订单、食物

例如:

df = spark.createDataFrame(pd.DataFrame([['A','B','A','C','A'],[1,1,2,1,3],['Eggs','Salad','Peaches','Bread','Water']],index=['User','Order','Food']).T)
我想把所有的食物连接成一个字符串,按顺序排序,按用户分组

如果我运行以下命令:

df.groupBy("User").agg(concat_ws(" $ ",collect_list("Food")).alias("Food List"))
我有一张单子,但食物没有按顺序排列

User Food List
B   Salad
C   Bread
A   Eggs $ Water $ Peaches

什么是将食物列表按顺序连接起来的好方法?

基于可能重复的评论,我能够想出一个解决方案

首先定义一个分拣机功能。这将获取一个结构,按顺序排序,然后返回以“$”分隔的字符串格式的项目列表

# define udf
def sorter(l):
  res = sorted(l, key=lambda x: x.Order)
  return ' $ '.join([item[1] for item in res])

sort_udf = udf(sorter,StringType())
然后创建结构并运行分拣机功能:

SortedFoodList = (df.groupBy("User")
                    .agg(collect_list(struct("Order","Food")).alias("food_list"))
                    .withColumn("sorted_foods",sort_udf("food_list"))
                    .drop("food_list)
                  )

尝试在此处使用
窗口

  • 构建数据框架
  • 创建窗口并应用
    udf
    来连接字符串:
  • 可能重复的
    from pyspark.sql.window import Window
    from pyspark.sql import functions as F
    from pyspark.sql.functions import mean, pandas_udf, PandasUDFType
    from pyspark.sql.types import *
    
    df = spark.createDataFrame(pd.DataFrame([['A','B','A','C','A'],[1,1,2,1,3],['Eggs','Salad','Peaches','Bread','Water']],index=['User','Order','Food']).T)
    df.show()
    
    +----+-----+-------+
    |User|Order|   Food|
    +----+-----+-------+
    |   A|    1|   Eggs|
    |   B|    1|  Salad|
    |   A|    2|Peaches|
    |   C|    1|  Bread|
    |   A|    3|  Water|
    +----+-----+-------+
    
    
    w = Window.partitionBy('User').orderBy('Order').rangeBetween(Window.unboundedPreceding, Window.unboundedFollowing)
    
    @pandas_udf(StringType(), PandasUDFType.GROUPED_AGG)
    def _udf(v):
        return ' $ '.join(v)
    
    df = df.withColumn('Food List', _udf(df['Food']).over(w)).dropDuplicates(['User', 'Food List']).drop(*['Order', 'Food'])
    df.show(truncate=False)
    
    +----+----------------------+
    |User|Food List             |
    +----+----------------------+
    |B   |Salad                 |
    |C   |Bread                 |
    |A   |Eggs $ Peaches $ Water|
    +----+----------------------+