【问题标题】:Group column of pyspark dataframe by taking only unique values from two columns通过仅从两列中获取唯一值来对 pyspark 数据框的列进行分组
【发布时间】:2019-09-02 07:06:52
【问题描述】:

我想根据 pyspark 数据框的两列中的唯一值对列进行分组。数据框的输出应该是这样的,一旦某个值用于 groupby 并且如果它存在于另一列中,那么它不应该重复。

    |------------------|-------------------|
    |   fruit          |     fruits        | 
    |------------------|-------------------|
    |    apple         |     banana        |
    |    banana        |     apple         |
    |    apple         |     mango         |
    |    orange        |     guava         |
    |    apple         |    pineapple      |
    |    mango         |    apple          |
    |   banana         |     mango         |
    |   banana         |    pineapple      |
    | -------------------------------------|

我尝试使用单列进行分组,需要对其进行修改或需要一些其他逻辑。

df9=final_main.groupBy('fruit').agg(collect_list('fruits').alias('values'))

我从上述查询中得到以下输出;

       |------------------|--------------------------------|
       |   fruit          |     values                     | 
       |------------------|--------------------------------|
       |  apple           | ['banana','mango','pineapple'] |
       |  banana          | ['apple']                      |
       |  orange          | ['guava']                      |
       |  mango           | ['apple']                      |
       |------------------|--------------------------------|

但我想要以下输出;

       |------------------|--------------------------------|
       |   fruit          |     values                     | 
       |------------------|--------------------------------|
       |  apple           | ['banana','mango','pineapple'] |
       |  orange          | ['guava']                      |
       |------------------|--------------------------------|

【问题讨论】:

  • 这真的取决于你的数据框的顺序,对吧?我是否正确假设如果香蕉在苹果之前加工,那么香蕉仍然存在?
  • 如果一旦对值进行分组,则从该分组数据中不应重复任何值,即如果香蕉先出现,那么它应该是 [banana | ['apple','mango','pineapple'] 然后 [orange | ['guava'] 是输出
  • spark 数据帧没有保证顺序,这对您的结果重要吗?
  • 没有。结果不重要

标签: pyspark pyspark-sql pyspark-dataframes


【解决方案1】:

这看起来像是一个连接组件问题。有几种方法可以做到这一点。

1. GraphFrames

您可以使用 GraphFrames 包。数据框的每一行都定义了一条边,您可以使用df 作为边创建一个图形,并将所有不同水果的数据框作为顶点。然后调用connectedComponents 方法。然后你可以操纵输出来得到你想要的。

2。只是 Pyspark

第二种方法有点小技巧。为每一行创建一个“哈希”,例如

hashed_df = df.withColumn('hash', F.sort_array(F.array(F.col('fruit'), F.col('fruits'))))

删除该列的所有非不同行

distinct_df = hashed_df.dropDuplicates(['hash'])

再次拆分项目

revert_df = distinct_df.withColumn('fruit', F.col('hash')[0]) \
    .withColumn('fruits', F.col('hash')[1])

按第一列分组

grouped_df = revert_df.groupBy('fruit').agg(F.collect_list('fruits').alias('group'))

如果 Pyspark 抱怨,您可能需要使用F.concat_ws“字符串化”您的哈希,但想法是一样的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-15
    • 2020-02-13
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多