【问题标题】:Lateral view explode strange behaviour侧视图爆炸奇怪行为
【发布时间】:2020-03-01 21:48:25
【问题描述】:

我正在连接两个数组列并将它们转换回数组。现在,当我应用爆炸时,什么都没有发生。使用 Spark 2.3。这里有什么奇怪的吗?

df = spark.createDataFrame([(1,25,['A','B','B','C'],['A','B','B','C']),(1,20,['A','A','B','C'],['A','B','B','C']),(1,20,['A','C','B','C'],['A','B','B','C']),(2,26,['X','Y','Z','C'],['A','B','B','C'])],['id','age','one','two'])
+---+---+------------+------------+
| id|age|         one|         two|
+---+---+------------+------------+
|  1| 25|[A, B, B, C]|[A, B, B, C]|
|  1| 20|[A, A, B, C]|[A, B, B, C]|
|  1| 20|[A, C, B, C]|[A, B, B, C]|
|  2| 26|[X, Y, Z, C]|[A, B, B, C]|
+---+---+------------+------------+

>>> df.createOrReplaceTempView('df')
>>> df2 = spark.sql('''select id,age, array(concat_ws(',', one, two)) as three from df''')
>>> df2.show()
+---+---+-----------------+
| id|age|            three|
+---+---+-----------------+
|  1| 25|[A,B,B,C,A,B,B,C]|
|  1| 20|[A,A,B,C,A,B,B,C]|
|  1| 20|[A,C,B,C,A,B,B,C]|
|  2| 26|[X,Y,Z,C,A,B,B,C]|
+---+---+-----------------+

>>> df2.createOrReplaceTempView('df2')
>>> spark.sql('''select id, age, four from df2 lateral view explode(three) tbl as four''').show() //not exploding
+---+---+---------------+
| id|age|           four|
+---+---+---------------+
|  1| 25|A,B,B,C,A,B,B,C|
|  1| 20|A,A,B,C,A,B,B,C|
|  1| 20|A,C,B,C,A,B,B,C|
|  2| 26|X,Y,Z,C,A,B,B,C|
+---+---+---------------+

请注意,我可以通过

>>> df2 = spark.sql('''select id,age, split(concat_ws(',', one, two),',') as three from df''')

但只是想知道为什么第一种方法不起作用。

【问题讨论】:

    标签: pyspark


    【解决方案1】:

    concat_ws 创建单个字符串列而不是数组:

    df.select(F.size(df.one)).show()
    df2.select(F.size(df2.three)).show()
    

    输出:

    +---------+
    |size(one)|
    +---------+
    |        4|
    |        4|
    |        4|
    |        4|
    +---------+
    +-----------+
    |size(three)|
    +-----------+
    |          1|
    |          1|
    |          1|
    |          1|
    +-----------+
    

    这意味着你的数组只有一个元素:

    df2.select(df2.three.getItem(0)).show()
    df2.select(df2.three.getItem(1)).show()
    df2.printSchema()
    

    输出:

    +---------------+
    |       three[0]|
    +---------------+
    |A,B,B,C,A,B,B,C|
    |A,A,B,C,A,B,B,C|
    |A,C,B,C,A,B,B,C|
    |X,Y,Z,C,A,B,B,C|
    +---------------+
    
    +--------+
    |three[1]|
    +--------+
    |    null|
    |    null|
    |    null|
    |    null|
    +--------+
    
    root
     |-- id: long (nullable = true)
     |-- age: long (nullable = true)
     |-- three: array (nullable = false)
     |    |-- element: string (containsNull = false)
    
    

    所以你实际应该使用的是 concat on spark >= 2.4:

    df3 = spark.sql('''select id,age, concat(one, two) as three from df''')
    df3.show(truncate=False)
    df3.printSchema()
    df3.select(df3.three.getItem(0)).show()
    df3.select(df3.three.getItem(1)).show()
    

    输出:

    +---+---+------------------------+
    |id |age|three                   |
    +---+---+------------------------+
    |1  |25 |[A, B, B, C, A, B, B, C]|
    |1  |20 |[A, A, B, C, A, B, B, C]|
    |1  |20 |[A, C, B, C, A, B, B, C]|
    |2  |26 |[X, Y, Z, C, A, B, B, C]|
    +---+---+------------------------+
    
    root
     |-- id: long (nullable = true)
     |-- age: long (nullable = true)
     |-- three: array (nullable = true)
     |    |-- element: string (containsNull = true)
    
    +--------+
    |three[0]|
    +--------+
    |       A|
    |       A|
    |       A|
    |       X|
    +--------+
    
    +--------+
    |three[1]|
    +--------+
    |       B|
    |       A|
    |       C|
    |       Y|
    +--------+
    

    使用 spark answer 为例)。

    【讨论】:

    • 你说对了一部分。您不能将 concat 与 2 个数组一起使用。它需要 StringType 或 BinaryType
    • Spark >= 2.4 允许数组列。你用什么版本的火花? Spark example)。
    • 不错@cronoik,但是当我看到concatconcat_ws 创建的两个数据框的dtypes 时,它们是相同的('arr', 'array<string>')。那么为什么一个字符串和另一个是数组。 ?
    • @PIG 你确定吗?它们都是我机器上的 array (Spark 2.4.1)。我已将 .printSchema() 的输出添加到我的答案中。你能再检查一下吗?
    【解决方案2】:

    使用 UDF 的示例方法:

    arraycat = F.udf(lambda x,y : x + y, ArrayType(StringType()))
    df = df.withColumn("combined", arraycat("one", "two"))
    df = df.withColumn("combined", F.explode("combined"))
    

    【讨论】:

      猜你喜欢
      • 2019-12-27
      • 2021-12-19
      • 2016-10-26
      • 1970-01-01
      • 2011-06-03
      • 2017-07-13
      • 2018-12-21
      • 2019-01-10
      • 1970-01-01
      相关资源
      最近更新 更多