有没有办法在pyspark中逐个访问数组(struct)中的多个JSON对象

有没有办法在pyspark中逐个访问数组(struct)中的多个JSON对象,json,apache-spark,dataframe,pyspark,pyspark-sql,Json,Apache Spark,Dataframe,Pyspark,Pyspark Sql,我对pyspark和json解析有点陌生,我被困在某些特定场景中。首先让我解释一下我要做的事情,我有一个json文件,其中有一个数据元素,该数据元素是一个数组,其中包含两个其他json对象。下面是给定的json文件 { "id": "da20d14c.92ba6", "type": "Data Transformation Node", "name": "", "topic": "", "x": 380, "y": 240, "typeo

我对pyspark和json解析有点陌生,我被困在某些特定场景中。首先让我解释一下我要做的事情,我有一个json文件,其中有一个数据元素,该数据元素是一个数组,其中包含两个其他json对象。下面是给定的json文件

 {
    "id": "da20d14c.92ba6",
    "type": "Data Transformation Node",
    "name": "",
    "topic": "",
    "x": 380,
    "y": 240,
    "typeofoperation":"join",
    "wires": [
        ["da20d14c.92ba6","da20d14c.93ba6"]
    ],
 "output":true, 
 "data":[
      {
         "metadata_id":"3434",
         "id":"1",
         "first_name":"Brose",
         "last_name":"Eayres",
         "email":"beayres0@archive.org",
         "gender":"Male",
         "postal_code":null
      },
      {
         "metadata_id":"3434",
         "id":"2",
         "first_name":"Brose",
         "last_name":"Eayres",
         "email":"beayres0@archive.org",
         "gender":"Male",
         "postal_code":null
      }
   ]

 }
现在我要做的是一个接一个地迭代该数据数组:这意味着迭代到json的第一个对象,将其存储到一个数据帧中,然后迭代到第二个对象,将其存储到另一个数据帧中,然后对其进行完全连接或任何类型的连接(可能吗)

如果是,如何在pyspark中执行此操作。到目前为止,我所做的是
试图将其分解,但数据是立即分解的,而不是逐个分解

from pyspark.sql import SparkSession
from pyspark.sql.functions import explode, col
from pyspark.sql.functions import *
from pyspark.sql import Row
from pyspark.sql import SQLContext
from pyspark import SparkConf, SparkContext

spark = SparkSession \
    .builder \
    .appName("Python Spark SQL basic example") \
    .getOrCreate()

sc = SparkContext.getOrCreate()

dataFrame = spark.read.option("multiline", "true").json("nodeWithTwoRddJoin.json")

dataNode = dataFrame.select(explode("data").alias("Data_of_node"))

dataNode.show()
但是上面的代码给了我一个集合数据集。比我以前

firstDataSet = dataNode.collect()[0]
secondDataSet =  dataNode.collect()[1] 

这些行给了我一行,我无法将其协调回dataframe。任何建议和解决方案

这将它们至少放在两个数据帧中

from pyspark.sql.functions import monotonically_increasing_id

df_with_id = dataNode.withColumn("id",monotonically_increasing_id())

max_id = df_with_id.agg({"id": "max"}).collect()[0]["max(id)"]


first_df = df_with_id.where("id = {maxid}".format(maxid=max_id))
second_df = df_with_id.where("id != {maxid}".format(maxid=max_id))

您需要在数据帧的每一行上应用一个映射,该映射将其中一列的内容拆分为两个新列。之后,将结果分离为两个数据帧并不重要。为了实现这一点,我使用了一个简单的函数,从数组返回所需的索引:

def splitArray(array, pos):
    return array[pos]
您可以这样应用此功能:

import pyspark.sql.functions as f

mapped = dataFrame.select(
    splitArray(f.col('data'), 0).alias('first'),
    splitArray(f.col('data'), 1).alias('second'))
(我使用内置的“col”函数来选择数据列。不确定是否有更优雅的方法来实现这一点。)

结果是:

+-----------------------------------------------------+-----------------------------------------------------+
|first                                                |second                                               
|
+-----------------------------------------------------+-----------------------------------------------------+
|[beayres0@archive.org, Brose, Male, 1, Eayres, 3434,]|[beayres0@archive.org, Brose, Male, 2, Eayres, 3434,]|
+-----------------------------------------------------+-----------------------------------------------------+
要删除不同dfs中的列,只需选择它们:

firstDataSet = mapped.select('first')
secondDataSet =  mapped.select('second)

首先让我问一下——它本质上只是一行数据,为什么需要一个完整的数据帧?您是否预计该行还会有其他收藏?或者你只是想连接两行吗?如果我可以在这两行上应用连接,那么也可以,因为我不知道我们是否可以在两行上应用连接,或者我们可以吗?我将这些行转换为数据帧的原因是,我的应用程序将数据帧作为输入,并将数据场作为输出。实际上,它不起作用,它在max_id=df_with_id.agg({“id”:“max”})处出现异常。collect()[0][“max(id)”]行,错误是AttributeError:module'json'没有属性'loads'耶,这样就可以了,进一步的查询将像email=firstDataSet.select(col(“first.email”))那样进行。非常感谢。你是个救生员