如何将两个spark Dataframe与一个可以有所不同的struct类型的字段结合起来?

时间:2018-02-12 10:34:17

标签: scala apache-spark struct spark-dataframe

我对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种不同类型的字段。

在数据框中导入文件没什么大不了的,但在展平过程中我可能想要在两个数据框架上进行联合,这些数据框架的帐户可能有不同的模式,当然我有以下错误:" Union只能在具有兼容列类型"

的表上执行

有没有办法轻松地做到这一点?如何引发这样的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"

1 个答案:

答案 0 :(得分:0)

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

import copy
...
schema_to_read = copy.deepcopy(df1.schema)
df2 = sql_context.read.format("json").schema(schema_to_read).load(path)