如何根据 JSON 字符串更改数据框模式?

How to change dataframe schema based on JSON string?

我已经下载了文章的语料库Aminar DBLP Version 11。语料库是一个巨大的文本文件(12GB),每一行都是一个 self-contained JSON 字符串:

'{"id": "100001334", "title": "Ontologies in HYDRA - Middleware for Ambient Intelligent Devices.", "authors": [{"name": "Peter Kostelnik", "id": "2702511795"}, {"name": "Martin Sarnovsky", "id": "2041014688"}, {"name": "Jan Hreno", "id": "2398560122"}], "venue": {"raw": "AMIF"}, "year": 2009, "n_citation": 2, "page_start": "43", "page_end": "46", "doc_type": "", "publisher": "", "volume": "", "issue": "", "fos": [{"name": "Lernaean Hydra", "w": 0.4178039}, {"name": "Database", "w": 0.4269269}, {"name": "World Wide Web", "w": 0.415332377}, {"name": "Ontology (information science)", "w": 0.459045082}, {"name": "Computer science", "w": 0.399807781}, {"name": "Middleware", "w": 0.5905041}, {"name": "Ambient intelligence", "w": 0.5440575}]}'

所有 JSON 个字符串都是换行分隔的。

当我使用 PySpark 打开文件时,它 returns 一个数据框,其中一列包含 JSON 个字符串:

df = spark.read.text(path_to_data)
df.show()
+--------------------+
|               value|
+--------------------+
|{"id": "100001334...|
|{"id": "100001888...|
|{"id": "100002270...|
|{"id": "100004108...|
|{"id": "10000571"...|
|{"id": "100007563...|
|{"id": "100008278...|
|{"id": "100008490...|

我需要访问 JSON 个字段来构建我的深度学习模型。

我的第一次尝试是尝试使用 JSON 方法打开文件,如 :

中所述
df = spark.read.option("wholeFile", True).option("mode", "PERMISSIVE").json(path_to_data)

但是所有提出的解决方案都花了很长时间 运行(超过 3 小时),没有任何结果可以显示。

我的第二次尝试是尝试从 JSON 字符串中解析 JSON object 以获取包含以下列的数据框:

df = spark.read.text(path_to_data)
schema = StructType([StructField("id", StringType()), StructField("title", StringType()), StructField("authors", ArrayType(MapType(StringType(), StringType()))), StructField("venue", MapType(StringType(), StringType()), True), StructField("year", IntegerType(), True), StructField("keywords", ArrayType(StringType()), True), StructField("references", ArrayType(StringType()), True), StructField("n_citation", IntegerType(), True), StructField("page_start", StringType(), True), StructField("page_end", StringType(), True), StructField("doc_type", StringType(), True), StructField("lang", StringType(), True), StructField("publisher", StringType(), True), StructField("volume", StringType(), True), StructField("issue", StringType(), True), StructField("issn", StringType(), True), StructField("isbn", StringType(), True), StructField("doi", StringType(), True), StructField("pdf", StringType(), True), StructField("url", ArrayType(StringType()), True), 
 StructField("abstract", StringType(), True), StructField("indexed_abstract", StringType(), True)])

datajson = df.withColumn("jsonData", from_json(col("value"),schema)).select("jsonData.*")

但它返回了异常“由于数据类型不匹配PySpark而无法解析列”,即使模式中每个字段的数据类型都是真实的(基于官方语料库网站 here)

我的第三次尝试是尝试将 JSON 字符串解析为 Map 数据类型:

casted = df.withColumn("value", from_json(df.value, MapType(StringType(),StringType())))

它给了我以下结果:

root
 |-- value: map (nullable = true)
 |    |-- key: string
 |    |-- value: string (valueContainsNull = true)

+--------------------+
|               value|
+--------------------+
|{id -> 100001334,...|
|{id -> 1000018889...|
|{id -> 1000022707...|
|{id -> 100004108,...|
|{id -> 10000571, ...|
|{id -> 100007563,...|
|{id -> 100008278,...|

现在,每一行都是有效的 JSON object 可以按如下方式访问:

row = casted.first()
row.value['id']
row.value['title']
row.value['authors']

现在,我的问题是如何将这个名为 'value' 的列的数据框转换为基于 JSON objects?

在不提供架构的情况下读取文件需要更长的时间。我试图将大文件分成较小的块以了解架构,但失败并显示在数据架构中找到重复的列:

我在具有提供的模式的同一数据集上尝试了以下方法并且有效。

from pyspark.sql.types import StructType,StructField,StringType,IntegerType,ArrayType
schema = StructType([StructField("id", StringType()), StructField("title", StringType()), StructField("authors", ArrayType(MapType(StringType(), StringType()))), StructField("venue", MapType(StringType(), StringType()), True), StructField("year", IntegerType(), True), StructField("keywords", ArrayType(StringType()), True), StructField("references", ArrayType(StringType()), True), StructField("n_citation", IntegerType(), True), StructField("page_start", StringType(), True), StructField("page_end", StringType(), True), StructField("doc_type", StringType(), True), StructField("lang", StringType(), True), StructField("publisher", StringType(), True), StructField("volume", StringType(), True), StructField("issue", StringType(), True), StructField("issn", StringType(), True), StructField("isbn", StringType(), True), StructField("doi", StringType(), True), StructField("pdf", StringType(), True), StructField("url", ArrayType(StringType()), True), 
 StructField("abstract", StringType(), True), StructField("indexed_abstract", StringType(), True)])

df = spark.read.option("wholeFile", True).option("mode", "PERMISSIVE").schema(schema).json("dblp_papers_v11.txt")

df.show()

输出


[![+----------+--------------------+--------------------+--------------------+----+--------+--------------------+----------+----------+--------+----------+----+--------------------+------+-----+----+----+--------------------+----+----+--------+--------------------+
|        id|               title|             authors|               venue|year|keywords|          references|n_citation|page_start|page_end|  doc_type|lang|           publisher|volume|issue|issn|isbn|                 doi| pdf| url|abstract|    indexed_abstract|
+----------+--------------------+--------------------+--------------------+----+--------+--------------------+----------+----------+--------+----------+----+--------------------+------+-----+----+----+--------------------+----+----+--------+--------------------+
| 100001334|Ontologies in HYD...|\[{name -> Peter K...|       {raw -> AMIF}|2009|    null|                null|         2|        43|      46|          |null|                    |      |     |null|null|                null|null|null|    null|                null|
|1000018889|Remote Policy Enf...|\[{name -> Fabio M...|{raw -> internati...|2013|    null|\[94181602, 150466...|         2|        70|      84|Conference|null|      Springer, Cham|      |     |null|null|10.1007/978-3-319...|null|null|    null|{"IndexLength":17...|
|1000022707|A SIMPLE OBSERVAT...|\[{name -> Jerzy M...|{raw -> Reports o...|2009|    null|\[1972178849, 2069...|         0|        19|      29|   Journal|null|                    |    44|     |null|null|                null|null|null|    null|{"IndexLength":49...|
| 100004108|Gait based human ...|\[{name -> Emdad H...|{raw -> internati...|2012|    null|\[1578000111, 2120...|         0|       319|     328|Conference|null|Springer, Berlin,...|      |     |null|null|10.1007/978-3-642...|null|null|    null|{"IndexLength":82...|
|  10000571|The GAME Algorith...|\[{name -> Pavel K...|{raw -> internati...|2008|    null|\[291899685, 19641...|         5|       859|     868|Conference|null|Springer, Berlin,...|      |     |null|null|10.1007/978-3-540...|null|null|    null|{"IndexLength":17...|
| 100007563|Formal Verificati...|\[{name -> George ...|{raw -> Software ...|2006|    null|\[1578963809, 1612...|         1|       650|     656|   Journal|null|                    |      |     |null|null|                null|null|null|    null|{"IndexLength":87...|
| 100008278|EMOTIONAL AND RAT...|\[{name -> Colin G...|{raw -> internati...|2010|    null|\[116282327, 14967...|         2|       238|        |Conference|null|                    |      |     |null|null|                null|null|null|    null|{"IndexLength":12...|
| 100008490|Principle-Based P...|\[{name -> Sandiwa...|{raw -> Natural L...|1991|    null|                null|         3|        43|      60|          |null|                    |      |     |null|null|                null|null|null|    null|                null|][1]][1]