【问题标题】:Create new column with an array of range of numbers使用一系列数字创建新列
【发布时间】:2018-12-12 08:45:22
【问题描述】:

所以我需要创建一个从 1 到 100 枚举的数字数组,作为每行的值作为额外的列。

array() 函数与一堆文字值一起使用是可行的,但肯定有一种方法可以使用/转换 Scala Range(a to b) 而不是单独列出每个数字?

spark.sql("SELECT key FROM schema.table")
  .otherCommands
  .withColumn("range", array(lit(1), lit(2), ..., lit(100)))

类似于:

withColumn("range", array(1 to 100))

【问题讨论】:

    标签: arrays scala apache-spark apache-spark-sql


    【解决方案1】:

    从 Spark 2.4 开始,您可以使用 [sequence][1] 函数 如果你有这个数据框:

    df.show()
    +--------+
    |column_1|
    +--------+
    |       1|
    |       2|
    |       3|
    |       0|
    +--------+
    

    如果你使用从 0 到 column_1 的序列函数,你会得到:

    df.withColumn("range", sequence(lit(0), col("column_1"))).show()
    +--------+------------+
    |column_1|       range|
    +--------+------------+
    |       1|      [0, 1]|
    |       2|   [0, 1, 2]|
    |       3|[0, 1, 2, 3]|
    |       0|         [0]|
    +--------+------------+
    

    对于这种情况,使用lit 设置这两个值:

    df.withColumn("range", sequence(lit(0), lit(100)))
    

    【讨论】:

      【解决方案2】:

      您可以在array 函数中使用lit 内置函数作为map 函数

      df.withColumn("range", array((1 to 100).map(lit(_)): _*))
      

      【讨论】:

        【解决方案3】:

        Spark 2.2+ 引入了一个新函数typedLit,无需在阵列上使用.map(lit(_)) 即可轻松解决此问题。来自文档:

        此函数与 lit 的区别在于此函数可以处理参数化的 scala 类型,例如:List、Seq 和 Map。

        如下使用:

        import org.apache.spark.sql.functions.typedLit
        
        df.withColumn("range", typedLit((1 to 100).toList))
        

        【讨论】:

          【解决方案4】:

          如果是 PySpark

          from pyspark.sql import functions as F
          DF.withColumn("range",F.array([F.lit(i) for i in range(1,11)]))
          

          希望以上回答有用。

          【讨论】:

            【解决方案5】:

            用 spark 版本 2.2.0 测试了这个解决方案

            请尝试这个简单的方法来做同样的事情:

            val df = spark.range(5).toDF("id")
            df.withColumn("range", lit(1 to 10 toArray)).show(false)
            

            代码的输出:

            +---+-------------------------------+
            |id |range                          |
            +---+-------------------------------+
            |0  |[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]|
            |1  |[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]|
            |2  |[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]|
            |3  |[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]|
            |4  |[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]|
            +---+-------------------------------+
            

            【讨论】:

            • 这不起作用:java.lang.RuntimeException: Unsupported literal type class [I [I@427a0746
            • 我在发布之前测试了解决方案。这是相同的输出。 val df = spark.range(5).toDF("id") df.withColumn("range", lit(1 to 10 toArray)).show(false)
            • 添加了相同@ChiMo的输出
            • 我使用的是 Spark 版本 2.0.2.6,也许对哪些版本支持这个有意见。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-12
            • 1970-01-01
            相关资源
            最近更新 更多