【问题标题】:Pyspark: cast array with nested struct to stringPyspark:将具有嵌套结构的数组转换为字符串
【发布时间】:2017-09-06 21:50:08
【问题描述】:

我有一个 pyspark 数据框,其中有一列名为 Filters: "数组>"

我想将我的数据框保存在 csv 文件中,为此我需要将数组转换为字符串类型。

我尝试转换它:DF.Filters.tostring()DF.Filters.cast(StringType()),但两种解决方案都会为过滤器列中的每一行生成错误消息:

org.apache.spark.sql.catalyst.expressions.UnsafeArrayData@56234c19

代码如下

from pyspark.sql.types import StringType

DF.printSchema()

|-- ClientNum: string (nullable = true)
|-- Filters: array (nullable = true)
    |-- element: struct (containsNull = true)
          |-- Op: string (nullable = true)
          |-- Type: string (nullable = true)
          |-- Val: string (nullable = true)

DF_cast = DF.select ('ClientNum',DF.Filters.cast(StringType())) 

DF_cast.printSchema()

|-- ClientNum: string (nullable = true)
|-- Filters: string (nullable = true)

DF_cast.show()

| ClientNum | Filters 
|  32103    | org.apache.spark.sql.catalyst.expressions.UnsafeArrayData@d9e517ce
|  218056   | org.apache.spark.sql.catalyst.expressions.UnsafeArrayData@3c744494

示例 JSON 数据:

{"ClientNum":"abc123","Filters":[{"Op":"foo","Type":"bar","Val":"baz"}]}

谢谢!!

【问题讨论】:

  • 你能分享一下最小代码吗?
  • 能否在转换前打印模式并显示数据。转换后也打印模式。
  • 架构似乎是正确的。
  • M 无法重现该问题。你能在转换之前显示数据吗?

标签: python sql apache-spark pyspark spark-dataframe


【解决方案1】:

我创建了一个示例 JSON 数据集来匹配该架构:

{"ClientNum":"abc123","Filters":[{"Op":"foo","Type":"bar","Val":"baz"}]}

select(s.col("ClientNum"),s.col("Filters").cast(StringType)).show(false)

+---------+------------------------------------------------------------------+
|ClientNum|Filters                                                           |
+---------+------------------------------------------------------------------+
|abc123   |org.apache.spark.sql.catalyst.expressions.UnsafeArrayData@60fca57e|
+---------+------------------------------------------------------------------+

你的问题最好使用explode()函数来解决,该函数将数组展平,然后是星号扩展符号:

s.selectExpr("explode(Filters) AS structCol").selectExpr("structCol.*").show()
+---+----+---+
| Op|Type|Val|
+---+----+---+
|foo| bar|baz|
+---+----+---+

要使其成为以逗号分隔的单列字符串:

s.selectExpr("explode(Filters) AS structCol").select(F.expr("concat_ws(',', structCol.*)").alias("single_col")).show()
+-----------+
| single_col|
+-----------+
|foo,bar,baz|
+-----------+

分解数组参考:Flattening Rows in Spark

“结构”类型的星号扩展引用:How to flatten a struct in a spark dataframe?

【讨论】:

  • 这会在顶部结构中创建列,而不是在单个列中将所有列的内容作为字符串
  • @alfredox 更新为添加单列版本。
【解决方案2】:

对于 Pyspark 中的我来说,to_json() 函数完成了这项工作。

与简单的转换为 String 相比,它还保留了“结构键”(不仅仅是“结构值”)。所以对于报告的例子,我会有类似的东西:

[{"Op":"foo","Type":"bar","Val":"baz"}]

这对我来说更有用,因为我必须将结果写入 Postgres 表。在这种格式下,我可以轻松地在 Postgres 中使用支持的 JSON 函数

【讨论】:

    【解决方案3】:

    你可以试试这个:

    DF = DF.withColumn('Filters', DF.Filters.cast("string"))
    

    【讨论】:

    • 我试过了,同样的结果:org.apache.spark.sql.catalyst.expressions.UnsafeArrayData@3
    • 我想说你必须运行 UDF,你可以应用一些逻辑将数组转换为字符串,然后选择新列
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 1970-01-01
    • 2020-01-04
    • 2021-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多