如何将两个spark数据帧与结构类型可以不同的字段结合在一起?

问题描述 投票:3回答:1

我对Apache Spark还是很陌生,有时仍然在挣扎。我正在尝试导入一个非常复杂的json文件,并将其展平,然后再将其保存到镶木地板文件中。

我的json文件是商店的树。

{
"id": "store02",
"name": "store name",
"domain": "domain",
"currency": "EUR",
"address1": "Somewhere",
"country": "GER",
"city": "Berlin",
"zipCode": "12345",
"timeZone": "CET",
"accounts" : [
    {
        "field1": "",
        "filed2": "",
        "field3": "",
        "optionnalArray1": [
            {
                "field1": "",
                "field2": ""
            }
        ],
        "optionnalArray2": ["aa", "bb"]
    }
],
"stores": [ .... ]    
}

每个商店都可以有一个由一组帐户组成的字段。一个帐户有3个必填字段和两个选项。因此,我有一个数据框,其中的字段可以具有3种不同的类型。

将文件导入数据帧没什么大不了,但是在扁平化过程中,我可能想对两个数据帧进行合并,并使用可能具有不同架构的帐户,当然,我会遇到以下错误:“只能执行联合在具有兼容列类型的表上”

是否可以轻松地做到这一点?如何火花可以毫无问题地导入此类json文件?

@ Ramesh

假设我有两个数据框。第一个是没有帐户的商店的数据框。第二个是带有帐户的商店的数据框。帐户是这样定义的结构:

val acquirerStruct = StructType(
    StructField("merchantId", StringType, nullable = true) ::
    StructField("name", StringType, nullable = true) ::
    Nil)

val accountStruct = StructType(
    StructField("acquirers", ArrayType(acquirerStruct), nullable = true) ::
        StructField("applicationCode", StringType, nullable = true) ::
        StructField("channelType", StringType, nullable = true) ::
        StructField("id", StringType, nullable = true) ::
        StructField("terminals", ArrayType(StringType), nullable = true) ::
        Nil)

[当我想合并两个数据框时,我在之前的第一个数据框上创建了一个列帐户:

df1.withColumn("account", array(lit(null).cast(accountStruct))).union(df2)

如果在df2中,所有行的帐户都具有与accountStruct相同的结构,则它可以正常工作。但这并不总是正确的。一个帐户可能没有终端或收单行。这在json中完全有效。在那种情况下,我有前面提到的错误。

"Union can only be performed on tables with the compatible column types"
scala apache-spark struct spark-dataframe
1个回答
0
投票

我在PySpark中遇到了同样的问题,我在读取不兼容的数据帧时通过提供模式解决了它

import copy
...
schema_to_read = copy.deepcopy(df1.schema)
df2 = sql_context.read.format("json").schema(schema_to_read).load(path)
© www.soinside.com 2019 - 2024. All rights reserved.