代码之家  ›  专栏  ›  技术社区  ›  Oleg Pavliv

数组列的spark聚合

  •  1
  • Oleg Pavliv  · 技术社区  · 8 年前

    我有一个带有数组列的数据帧。

    val json = """[
    {"id": 1, "value": [11, 12, 18]},
    {"id": 2, "value": [23, 21, 29]}
    ]"""
    
    val df = spark.read.json(Seq(json).toDS)
    
    scala> df.show
    +---+------------+
    | id|       value|
    +---+------------+
    |  1|[11, 12, 18]|
    |  2|[23, 21, 29]|
    +---+------------+
    

    现在我需要对value列应用不同的聚合函数。 我可以打电话 explode groupBy

    df.select($"id", explode($"value").as("value")).groupBy($"id").agg(max("value"), avg("value")).show
    
    +---+----------+------------------+
    | id|max(value)|        avg(value)|
    +---+----------+------------------+
    |  1|        18|13.666666666666666|
    |  2|        29|24.333333333333332|
    +---+----------+------------------+
    

    这里让我困扰的是,我将我的数据帧分解成一个更大的数据帧,然后将其还原为原来的调用 groupBy公司 .

    有没有更好(即更有效)的方法来调用数组列上的聚合函数?也许我可以实现自定义项,但我不想自己实现所有聚合自定义项。

    编辑。某人引用 this SO question size 工作正常吗

    scala> df.select($"id", size($"value")).show
    +---+-----------+
    | id|size(value)|
    +---+-----------+
    |  1|          3|
    |  2|          3|
    +---+-----------+
    

    avg 或 max 不要工作。

    1 回复  |  直到 8 年前
        1
  •  8
  •   Wade Jensen    8 年前

    简而言之,答案是否定的 ,则必须实现自己的自定义项才能在数组列上进行聚合。至少在Spark的最新版本中(编写本文时为2.3.1)。正如您正确断言的那样,它不是非常有效,因为它迫使您分解行,或者支付在DataSetaAPI中工作的序列化和反序列化成本。

    对于可能发现此问题的其他人,要使用数据集以类型安全的方式编写聚合,可以使用 Aggregator

    更长远的答案是,这个功能即将推出 在ApacheSpark2.4中。

    SPARK-23899

    • 数组\u max
    • 骨料
    • 地图
    • 数组\u distinct
    • 数组\u连接

    还有很多其他的

    Screencap slide 11 of Extending Spark SQL API with Easier to Use Array Types Operations

    “这次谈话” Extending Spark SQL API with Easier to Use Array Types Operations

    如果它被发布了,你就可以使用 max average 有点棘手。 奇怪的是,数组\u sum不存在,但它可以从 aggregate

    def sum_array(array_col: Column) = aggregate($"my_array_col", 0, (s, x) => s + x, s => s) df.select(sum_array($"my_array_col") 其中,零值是聚合缓冲区的初始状态。

    正如你所指出的 size 已经可以获得数组的长度,这意味着可以计算平均值。

    推荐文章