【问题标题】:How to create a column of arrays whose values are coming from one column and their length is coming from another column in pyspark dataframes?如何创建一列数组,其值来自一列并且它们的长度来自pyspark数据帧中的另一列?
【发布时间】:2020-08-03 02:09:12
【问题描述】:

在 pyspark 数据框中,我需要创建一个新的 ArrayType(StringType()) 列,其值来自 StringType() 列,它们的长度来自另一个 ArrayType(StringType()) 列的长度。有点像具有动态长度的 array_repeat。

输入

+-------------+-------------+
|col1         |col2         |
+-------------+-------------+
|[1,2]        |‘a’          |
|[1,2,3]      |‘b’          |
+-------------+-------------+

输出

+-------------+-------------+----------------+
|col1         |col2         |col3            |
+-------------+-------------+----------------+
|[1,2]        |‘a’          |['a’,‘a’]       |
|[1,2,3]      |‘b’          |['b’,’b’,’b’]   |
+-------------+----------- -+----------------+

谢谢

【问题讨论】:

    标签: python apache-spark pyspark


    【解决方案1】:

    另一种选择-

    加载提供的测试数据

    val df = spark.sql(
          """
            |select col1, col2
            |from values
            | (array(1, 2), 'a'),
            | (array(1, 2, 3), 'b')
            | T(col1, col2)
          """.stripMargin)
        df.show(false)
        df.printSchema()
    
        /**
          * +---------+----+
          * |col1     |col2|
          * +---------+----+
          * |[1, 2]   |a   |
          * |[1, 2, 3]|b   |
          * +---------+----+
          *
          * root
          * |-- col1: array (nullable = false)
          * |    |-- element: integer (containsNull = false)
          * |-- col2: string (nullable = false)
          */
    

    Alternative-1

    
        // alternative-1
        df.withColumn("col3", expr("array_repeat(col2, size(col1))"))
          .show(false)
    
        /**
          * +---------+----+---------+
          * |col1     |col2|col3     |
          * +---------+----+---------+
          * |[1, 2]   |a   |[a, a]   |
          * |[1, 2, 3]|b   |[b, b, b]|
          * +---------+----+---------+
          */
    

    备选方案 2

    
        // alternative-2
        df.withColumn("col3", expr(s"TRANSFORM(col1, x -> col2)"))
          .show(false)
    
        /**
          * +---------+----+---------+
          * |col1     |col2|col3     |
          * +---------+----+---------+
          * |[1, 2]   |a   |[a, a]   |
          * |[1, 2, 3]|b   |[b, b, b]|
          * +---------+----+---------+
          */
    

    【讨论】:

      【解决方案2】:

      使用array_repeat + size

      import pyspark.sql.functions as f
      
      df = spark.createDataFrame([[[1,2],'a'], [[1,2,3], 'b']], ['col1', 'col2'])
      
      df.withColumn('col3', f.array_repeat('col2', f.size('col1'))).show()
      
      +---------+----+---------+
      |     col1|col2|     col3|
      +---------+----+---------+
      |   [1, 2]|   a|   [a, a]|
      |[1, 2, 3]|   b|[b, b, b]|
      +---------+----+---------+
      

      如果在任何情况下这不起作用,您可以编写一个 udf 来执行此操作:

      from pyspark.sql.types import StringType, ArrayType
      import pyspark.sql.functions as f
      
      @f.udf(ArrayType(StringType()))
      def repeat_sizeof(col1, col2):
          return [col1] * len(col2)
      
      df.withColumn('col3', repeat_sizeof('col2', 'col1')).show()
      
      +---------+----+---------+
      |     col1|col2|     col3|
      +---------+----+---------+
      |   [1, 2]|   a|   [a, a]|
      |[1, 2, 3]|   b|[b, b, b]|
      +---------+----+---------+
      

      【讨论】:

      • 我已经尝试过了,但是我得到了“column is not iterable”错误。
      • 你的 spark 版本是什么?在 spark 3 中测试了这个作品
      • 我在 2.4。谢谢
      • 嗯,我认为它也可以。如果没有,那么您可能需要使用 UDF 执行此操作。
      猜你喜欢
      • 2021-08-19
      • 2020-10-12
      • 2020-11-22
      • 2019-09-04
      • 2018-03-14
      • 1970-01-01
      • 1970-01-01
      • 2023-01-25
      • 1970-01-01
      相关资源
      最近更新 更多