【问题标题】:spark higher order function transform output struct火花高阶函数变换输出结构
【发布时间】:2020-02-20 01:15:55
【问题描述】:

我如何transform 一个结构数组再次使用 spark 高阶函数的结构?

数据集:

case class Foo(thing1:String, thing2:String, thing3:String)
case class Baz(foo:Foo, other:String)
case class Bar(id:Int, bazes:Seq[Baz])
import spark.implicits._
val df = Seq(Bar(1, Seq(Baz(Foo("first", "second", "third"), "other"), Baz(Foo("1", "2", "3"), "else")))).toDF
df.printSchema
df.show(false)

我想连接所有thing1, thign2, thing3,但保留每个barother 属性。

一个简单的:

scala> df.withColumn("cleaned", expr("transform(bazes, x -> x)")).printSchema
root
 |-- id: integer (nullable = false)
 |-- bazes: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- foo: struct (nullable = true)
 |    |    |    |-- thing1: string (nullable = true)
 |    |    |    |-- thing2: string (nullable = true)
 |    |    |    |-- thing3: string (nullable = true)
 |    |    |-- other: string (nullable = true)
 |-- cleaned: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- foo: struct (nullable = true)
 |    |    |    |-- thing1: string (nullable = true)
 |    |    |    |-- thing2: string (nullable = true)
 |    |    |    |-- thing3: string (nullable = true)
 |    |    |-- other: string (nullable = true)

只会把东西复制过来。

所需的连接操作:

 df.withColumn("cleaned", expr("transform(bazes, x -> concat(x.foo.thing1, '::', x.foo.thing2, '::', x.foo.thing3))")).printSchema

很遗憾,将删除 other 列中的所有值:

 +---+----------------------------------------------------+-------------------------------+
|id |bazes                                               |cleaned                        |
+---+----------------------------------------------------+-------------------------------+
|1  |[[[first, second, third], other], [[1, 2, 3], else]]|[first::second::third, 1::2::3]|
+---+----------------------------------------------------+-------------------------------+

如何保留这些? 试图保留元组:

df.withColumn("cleaned", expr("transform(bazes, x -> (concat(x.foo.thing1, '::', x.foo.thing2, '::', x.foo.thing3), x.other))")).printSchema

失败:

.AnalysisException: cannot resolve 'named_struct('col1', concat(namedlambdavariable().`foo`.`thing1`, '::', namedlambdavariable().`foo`.`thing2`, '::', namedlambdavariable().`foo`.`thing3`), NamePlaceholder(), namedlambdavariable().`other`)' due to data type mismatch: Only foldable string expressions are allowed to appear at odd position, got: NamePlaceholder; line 1 pos 22;

编辑

想要的输出:

  • 一个包含内容的新列:

    [[first::second::third, other], [1::2::3,else]

保留列other

【问题讨论】:

  • 你能添加预期的输出吗?它不能直接访问 bcoz foo 和其他共享相同的层次结构。所以请添加您想要的输出。所以我可以为您的问题添加答案。
  • 现在清楚了吗?
  • 是的,我已经添加了答案,请检查并接受
  • ou concat other,但我想将其作为输出结构中的单独列保留。
  • 好的,明白了

标签: apache-spark struct apache-spark-sql higher-order-functions complextype


【解决方案1】:

通过这种方式,您可以实现您想要的输出。您不能直接访问其他值 bcoz foo 并且其他值共享相同的层次结构。所以你需要单独访问其他。

scala>  df.withColumn("cleaned", expr("transform(bazes, x -> struct(concat(x.foo.thing1, '::', x.foo.thing2, '::', x.foo.thing3),cast(x.other as string)))")).show(false)
+---+----------------------------------------------------+------------------------------------------------+
|id |bazes                                               |cleaned                                         |
+---+----------------------------------------------------+------------------------------------------------+

打印架构

scala>  df.withColumn("cleaned", expr("transform(bazes, x -> struct(concat(x.foo.thing1, '::', x.foo.thing2, '::', x.foo.thing3),cast(x.other as string)))")).printSchema
root
 |-- id: integer (nullable = false)
 |-- bazes: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- foo: struct (nullable = true)
 |    |    |    |-- thing1: string (nullable = true)
 |    |    |    |-- thing2: string (nullable = true)
 |    |    |    |-- thing3: string (nullable = true)
 |    |    |-- other: string (nullable = true)
 |-- cleaned: array (nullable = true)
 |    |-- element: struct (containsNull = false)
 |    |    |-- col1: string (nullable = true)
 |    |    |-- col2: string (nullable = true)

如果您还有任何与此相关的问题,请告诉我。

【讨论】:

  • 请查看更新后的所需输出。你连接other,但我想将它作为一个单独的列保留在输出的结构中。
  • 有趣。你能解释一下为什么:df.withColumn("cleaned", expr("transform(bazes, x -> struct(concat(x.foo.thing1, '::', x.foo.thing2, '::', x.foo.thing3),x.other))")).show(false) 不起作用吗?也就是说,您似乎仍然将另一列拉入 concat 操作。
  • 我的意思是:结构仍然只包含一列。我希望结构包含两个单独的列。
  • 在高阶函数中,它无法识别 x.other 列来为结构创建新值,这就是我在 concat 函数中使用 x.other 的原因。
  • 有趣的是,即使一个字段是string,您仍然需要将其显式转换为string 才能工作。否则它只会抛出异常
猜你喜欢
  • 1970-01-01
  • 2020-09-09
  • 2017-02-28
  • 1970-01-01
  • 1970-01-01
  • 2021-05-31
  • 2017-02-22
  • 2020-08-18
  • 2022-07-15
相关资源
最近更新 更多