在 PySpark 中展开 json 列 - 架构问题 - AttributeError: 'tuple' object has no attribute 'name'

Posted

技术标签:

【中文标题】在 PySpark 中展开 json 列 - 架构问题 - AttributeError: \'tuple\' object has no attribute \'name\'【英文标题】:Expand json column in PySpark - schema issues - AttributeError: 'tuple' object has no attribute 'name'在 PySpark 中展开 json 列 - 架构问题 - AttributeError: 'tuple' object has no attribute 'name' 【发布时间】:2021-12-23 23:40:59 【问题描述】:

我正在使用 pyspark 从多行 json 对象中提取数据。我可以读取文件,但无法解析几何列的内容。

整体表格的示例如下所示。

+--------------------+--------------------+-------+
|            geometry|          properties|   type|
+--------------------+--------------------+-------+
|[13.583336, 37.2...|AGRIGENTO, AGRIG...|Feature|
|[13.584538, 37.3...|AGRIGENTO, AGRIG...|Feature|
|[13.657838, 37.3...|FAVARA, AGRIGENT...|Feature|
|[13.846247, 37.3...|CANICATTÌ, AGRI...|Feature|
|[13.616626, 37.4...|ARAGONA, AGRIGEN...|Feature|
|[13.108426, 37.6...|SAMBUCA DI SICIL...|Feature|
|[16.709313, 41.0...|GRUMO APPULA, BA...|Feature|
|[12.670994, 41.4...|NETTUNO, ROMA, 6...|Feature|
|[12.501805, 42.1...|CASTELNUOVO DI P...|Feature|
|[12.608105, 41.4...|ANZIO, ROMA, b54...|Feature|
+--------------------+--------------------+-------+

这是json几何列的单行格式

"geometry":"type":"Point","coordinates":[13.583336,37.270182] 

当我提取架构时,这就是它的样子

StructType(List(StructField("geometry",StructType(List(StructField("coordinates",ArrayType(DoubleType,true),true),StructField("type",StringType,true))),true)

但是,当我尝试在 PySpark 中设置架构以导入数据时,出现以下错误。

AttributeError: 'tuple' 对象没有属性 'name'

这是我正在使用的代码。

from pyspark.sql.types import StructField, StructType, StringType, FloatType, ArrayType, DoubleType
import pyspark.sql.functions as F

df = spark.read.option("multiLine", False).option("mode", "PERMISSIVE").json('Italy/it_countrywide-addresses-country.geojson')


schema = StructType([
    (StructField("coordinates",
                 ArrayType(DoubleType())),
     StructField("type",StringType()))
])

df.withColumn("geometry", F.from_json("geometry", schema)).select(col('geometry.*')).show()

我欢迎你的 cmets。

【问题讨论】:

我没有回答这个问题,但找到了解决方法。导入文件两次(必须是更好的方法)并在其中一个导入上获取模式并将其用作第二次导入的参数。 json_schema = spark.read.option("multiLine", False).option("mode", "PERMISSIVE").json('Italy/it_countrywide-addresses-country.geojson').schema df_with_schema = spark.read.option("multiLine", False).option("mode", "PERMISSIVE").schema(json_schema).json('Italy/it_countrywide-addresses-country.geojson') df_with_schema.printSchema() coordinates = df_with_schema.select(F.col('geometry.coordinates')) 如果您有可行的解决方案,请随时回答您自己的问题。它可能会帮助其他人,并且不会阻止人们提供“更好”的答案。 错误是说你在 StructType 数组中有额外的(StructType 应该是 StructField 的数组,而不是元组。 @Emmathanx !你救了我的 a$$ 我要疯了 ^^ 【参考方案1】:

最终,我的目标是读取 json 文件并访问嵌套值。我收到的错误是因为我没有正确创建架构。纠正此错误的最佳方法是避免手动创建架构。

为此,我使用了您可以通过在 json 文件上调用 .schema 来创建的架构。这解决了您自己创建架构的任何问题。

这样做的缺点是您实际上是两次导入文件,毫无疑问,这可以进一步优化以避免这种情况。

json_schema = spark.read.option("multiLine", False).option("mode", "PERMISSIVE").json('Italy/it_countrywide-addresses-country.geojson').schema 
df_with_schema = spark.read.option("multiLine", False).option("mode", "PERMISSIVE").schema(json_schema).json('Italy/it_countrywide-addresses-country.geojson') 
df_with_schema.printSchema() 

# Select coordinates array
coordinates = df_with_schema.select(F.col('geometry.coordinates'))

# select single value from coordinates array
single_value_from_coordinates_array = df_with_schema.select(F.col('geometry.coordinates')[0])

# create my own dataframe choosing multiple columns from json file
multi_columns = df_with_schema.select(F.col('geometry.coordinates'), F.col('properties.city'))

【讨论】:

以上是关于在 PySpark 中展开 json 列 - 架构问题 - AttributeError: 'tuple' object has no attribute 'name'的主要内容,如果未能解决你的问题,请参考以下文章

在 Pyspark 中爆炸不是数组的结构列

使用 pyspark 解析 JSON 时嵌套动态模式不起作用

如何在pyspark中将JSON字符串转换为JSON对象

pySpark - 在插入数据库之前将整个数据框列转换为 JSON 对象

python中具有json行类型的PySpark Dataframe列

如何使用 PySpark 将 JSON 列类型写入 Postgres?