如何将 JSON 格式的单行 Spark 数据框分解为多行?

Posted

技术标签:

【中文标题】如何将 JSON 格式的单行 Spark 数据框分解为多行?【英文标题】:How to explode a one row Spark dataframe in JSON format to multiple rows? 【发布时间】:2022-01-06 17:33:34 【问题描述】:

上下文:我正在学习 PySpark,我正在尝试对推文进行情绪分析。加载数据(即 JSON 格式)后,我想将其存储在 Spark Dataframe 中以进行预处理(删除不必要的符号/单词)。目前,我正在使用一个我想消除的中间步骤:我将 JSON 加载到 pandas DataFrame 中,然后加载到 spark Dataframe 中,一切正常。

但是,当将 JSON 直接加载到 PySpark DataFrame 时,所有数据仅存储在一行中。

我如何加载数据:

df = spark.read.json("dbfs:/FileStore/tables/json_twitter.json").select("full_text")

df仅由一行一列(full_text)构成,格式如下:

"0": "Hello", "1": "Tweet","2": "Bye"

我怎样才能有效地把它变成一个“正常”的数据框,每个单词都有一行?

谢谢

【问题讨论】:

【参考方案1】:

如果fulltext 中的值是字符串,您可以先使用from_json 示例将其转换为映射类型

from pyspark.sql import functions as F
from pyspark.sql import types as T

df = df.withColumn("fulltext",F.from_json("fulltext",T.MapType(T.StringType(),T.StringType())))

在应用explode 函数将值拆分为多行之前,例如:

from pyspark.sql import functions as F
from pyspark.sql import types as T

df = df.select(F.explode("fulltext"))

df.show(truncate=False)
+---+-----+
|key|value|
+---+-----+
|0  |Hello|
|1  |Tweet|
|2  |Bye  |
+---+-----+

编辑 1

如果fulltext里面的值是一个结构体,你可以先

    使用cast将其转换为字符串 使用regexp_replace 替换多余的字符大括号 使用split以逗号分隔字符串 使用explode 分解拆分值以获得所需的行

例如

from pyspark.sql import functions as F
from pyspark.sql import types as T

df = df.withColumn("fulltext",F.col("fulltext").cast("string"))
df.printSchema() # only for debugging purposes
df.show() # only for debugging purposes

df = df.withColumn("fulltext",F.explode(F.split(F.regexp_replace("fulltext","\\|\\",""),",")))

df.show() # only for debugging purposes
root
 |-- fulltext: string (nullable = false)

+-------------------+
|           fulltext|
+-------------------+
|Hello, Tweet, Bye|
+-------------------+

+--------+
|fulltext|
+--------+
|   Hello|
|   Tweet|
|     Bye|
+--------+

【讨论】:

不是字符串。它采用上述格式,采用 JSON 格式。运行第一个命令时,我收到以下错误:“AnalysisException:由于数据类型不匹配,无法解析‘条目’:参数 1 需要字符串类型,但是,‘full_text’属于结构类型。;‘项目 [ from_json(MapType(StringType,StringType,true), full_text#356, Some(Etc/UTC)) AS full_text#417] +- 项目 [full_text#356]"。有什么解决方法吗?我可以将其类型更改为字符串吗? 是的,您可以在运行上述df = df.withColumn("fulltext", F.col("fulltext").cast("string"))之前将日期类型更改为字符串 我试过这样做,但是当我运行 df = df.withColumn("fulltext",F.from_json("fulltext",T.MapType(T.StringType(),T.StringType()))) 时,我得到一个只有一个空值的 Dataframe @FHSilva 我已经用另一种方法更新了答案。我最初并不知道 fulltext 在您的场景中是一个结构。在我的环境中,它被复制为 map 类型。让我知道这是否适合您。 原来如此,谢谢!

以上是关于如何将 JSON 格式的单行 Spark 数据框分解为多行?的主要内容,如果未能解决你的问题,请参考以下文章

Spark:如何将多行转换为具有多列的单行?

使用 Spark 规划 JSON 的 DynamoDB 数据格式

如何将 JSON 格式的数据展平为 spark 数据框

如何使用 spark/scala 将 json 字符串格式化为 MongoDB 文档样式?

如何将我的节点 winston JSON 输出更改为单行

在 spark 中读取单行 json,其中列键是可变的