如何根据 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]
我已经下载了文章的语料库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]