【问题标题】:Create array of literals and columns from List of Strings in Spark SQL从 Spark SQL 中的字符串列表创建文字和列数组
【发布时间】:2019-03-14 03:34:01
【问题描述】:

我正在尝试在 Scala 中定义将字符串列表作为输入的函数,并将它们转换为传递给下面代码中使用的数据帧数组参数的列。

val df = sc.parallelize(Array((1,1),(2,2),(3,3))).toDF("foo","bar")
val df2 = df
        .withColumn("columnArray",array(df("foo").cast("String"),df("bar").cast("String")))
        .withColumn("litArray",array(lit("foo"),lit("bar")))

更具体地说,我想创建函数 colFunction 和 litFunction(或者如果可能的话,只创建一个函数),它们将字符串列表作为输入参数,可以按如下方式使用:

val df = sc.parallelize(Array((1,1),(2,2),(3,3))).toDF("foo","bar")
val colString = List("foo","bar")
val df2 = df
         .withColumn("columnArray",array(colFunction(colString))
         .withColumn("litArray",array(litFunction(colString)))

我尝试将colString 映射到具有所有转换的列数组,但这不起作用。关于如何实现这一点的任何想法?非常感谢您阅读该问题以及任何建议/解决方案。

【问题讨论】:

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


    【解决方案1】:

    Spark 2.2+:

    SPARK-19254 中添加了对 Seq、Map 和 Tuple (struct) 文字的支持。根据to tests:

    import org.apache.spark.sql.functions.typedLit
    
    typedLit(Seq("foo", "bar"))
    

    火花

    只需 map 和 lit 并用 array 包装:

    def asLitArray[T](xs: Seq[T]) = array(xs map lit: _*)
    
    df.withColumn("an_array", asLitArray(colString)).show
    // +---+---+----------+
    // |foo|bar|  an_array|
    // +---+---+----------+
    // |  1|  1|[foo, bar]|
    // |  2|  2|[foo, bar]|
    // |  3|  3|[foo, bar]|
    // +---+---+----------+
    

    关于从Seq[String] 到Column 类型Array 的转换,此功能已由以下人员提供:

    def array(colName: String, colNames: String*): Column 
    

    或

    def array(cols: Column*): Column
    

    例子:

    val cols = Seq("bar", "foo")
    
    cols match { case x::xs => df.select(array(x, xs:_*)) 
    // or 
    df.select(array(cols map col: _*))
    

    当然,所有列都必须属于同一类型。

    【讨论】:

    • 请原谅我的无知,但那东西叫什么? array(xs map lit: _*),我觉得很困惑。
    • @AlbertoBonsanto 你原谅了 ;) 说真的,虽然这是 Scala 解包参数的方式。我们在这里使用的array 实现具有以下签名:array(cols: Column*) 其中* 标记可变参数。这意味着它可以被称为array(x, y, z)。因为我们传递了一个序列,所以它必须被解包,标记为: _*。相当于 Python def foo(*args): ...; foo(*[x, y, z])。
    • 非常感谢@zero323!我仍然不知道如何在我的问题中定义我称之为 colFunction(colString) 的东西,我需要返回一个列值(而不是文字)的数组。是否也可以使用与您提供的功能类似的功能?
    • 你不需要自定义函数。像df.select(array($"foo", $"bar"))一样直接使用array。
    • @zero323 这将是处理 List[List[String]] 的更大过程的一部分,因此我正在寻找一个将 List[String] 转换为文字数组的函数(您已经提供了),但也作为实际列值的数组。这可能吗?
    猜你喜欢
    • 2019-07-07
    • 1970-01-01
    • 2011-08-20
    • 2020-04-21
    • 2022-11-16
    • 2020-02-29
    • 2020-07-04
    • 2016-02-13
    • 2011-04-20
    相关资源
    最近更新 更多