【问题标题】:Spark explode function not working as expected火花爆炸功能未按预期工作
【发布时间】:2020-08-28 20:54:54
【问题描述】:

我正在尝试扁平化一个复杂的 XML 结构,下面是 XML 文件 -

<root>
<ATS  name="exp_Change_Rec">
<EXP1>
<EXP1INT >
<ExPFLDs>
<ExPFLD  precision="10" name="COL1" output="true"/>
<ExPFLD  precision="20" name="COL2" output="true"/>
<ExPFLD  precision="30" name="COL3" output="true"/>
<ExPFLD  precision="40" name="COL4" output="true"/>
</ExPFLDs>
</EXP1INT>
</EXP1>
</ATS>

<ATS  name="exp_Change_Flag">
<EXP1>
<EXP1INT >
<ExPFLDs>
<ExPFLD precision="10" name="COL5" output="true"/>
<ExPFLD precision="20" name="COL6" output="true"/>
<ExPFLD precision="30" name="COL7" output="true"/>
</ExPFLDs>
</EXP1INT>
</EXP1>
</ATS>
</root>

我期望输出为 -

Name                  Value
exp_Change_Rec        COL1
exp_Change_Rec        COL2
exp_Change_Rec        COL3
exp_Change_Rec        COL4
exp_Change_Flag       COL5
exp_Change_Flag       COL6
exp_Change_Flag       COL7

我正在通过 databricks spark xml 执行,但它正在创建某种笛卡尔连接 -

import org.apache.spark.sql.SparkSession
import com.databricks.spark.xml.
val df1 = spark.read.option("rowTag", "root").xml("file:///home/sv-infopcdq/spark/sample.xml")
val df2 = df1.withColumn("_name", explode($"ATS._name"))
df2.withColumn("COL_NAMES", explode($"ATS.EXP1.EXP1INT.ExPFLDs.ExPFLD")).show(100)

+--------------------+---------------+--------------------+
|                 ATS|          _name|           COL_NAMES|
+--------------------+---------------+--------------------+
|[[[[[[[, COL1, tr...| exp_Change_Rec|[[, COL1, true, 2...|
|[[[[[[[, COL1, tr...| exp_Change_Rec|[[, COL5, true,],...|
|[[[[[[[, COL1, tr...|exp_Change_Flag|[[, COL1, true, 2...|
|[[[[[[[, COL1, tr...|exp_Change_Flag|[[, COL5, true,],...|

在这里,我看到 COL1 同时发出了 exp_Change_Rec 和 exp_Change_Flag。 请有任何建议。

当我尝试分解一列时,输出工作正常,但是当我尝试分解所有列时,它显示笛卡尔连接

如果我希望输出为

  Name                   Value    Precision
    exp_Change_Rec        COL1      10
    exp_Change_Rec        COL2      20
    exp_Change_Rec        COL3      30
    exp_Change_Rec        COL4      40
    exp_Change_Flag       COL5      10
    exp_Change_Flag       COL6      20
    exp_Change_Flag       COL7      30

如果我想扩展正确答案以在其中包含“精度”,它不起作用 -

xml_df.withColumn("_name", ($"_name"))
    .withColumn("COL_NAMES",explode($"EXP1.EXP1INT.ExPFLDs.ExPFLD._name")
.withColumn("COL_NAMES",explode($"EXP1.EXP1INT.ExPFLDs.ExPFLD._precision")).drop("EXP1")
      .select($"_name".as("Name"), $"COL_NAMES".as("Value"))

请在同一级别上展开多个列的任何解决方法?

【问题讨论】:

    标签: scala apache-spark databricks


    【解决方案1】:

    首先,您需要更正您的rootTagrowTag 才能继续进行。由于您使用rowtag 作为父/根标签,即(root),因此它正在将整个 XML 视为一条记录...这就是您获得单块记录而不是单独记录格式的地方...请参阅下面的实现细节。


    我使用了explode 函数,我选择了您想要的确切列,如下所示...

     val xml_df = spark.read.
          format("com.databricks.spark.xml")
          .option("rootTag", "root")
          .option("rowTag", "ATS")
          .option("nullValue","")
          .load(f.getAbsolutePath)
          xml_df.show
        xml_df.printSchema()
    
       val test =  xml_df.withColumn("_name", ($"_name"))
        .withColumn("COL_NAMES",explode($"EXP1.EXP1INT.ExPFLDs.ExPFLD._name")).drop("EXP1")
          .select($"_name".as("Name"), $"COL_NAMES".as("Value"))
        test.printSchema()
        test.show(100,false)
    

    你的预期输出:

    +--------------------+---------------+
    |                EXP1|          _name|
    +--------------------+---------------+
    |[[[[[, COL1, true...| exp_Change_Rec|
    |[[[[[, COL5, true...|exp_Change_Flag|
    +--------------------+---------------+
    
    root
     |-- EXP1: struct (nullable = true)
     |    |-- EXP1INT: struct (nullable = true)
     |    |    |-- ExPFLDs: struct (nullable = true)
     |    |    |    |-- ExPFLD: array (nullable = true)
     |    |    |    |    |-- element: struct (containsNull = true)
     |    |    |    |    |    |-- _VALUE: string (nullable = true)
     |    |    |    |    |    |-- _name: string (nullable = true)
     |    |    |    |    |    |-- _output: boolean (nullable = true)
     |    |    |    |    |    |-- _precision: long (nullable = true)
     |-- _name: string (nullable = true)
    
    root
     |-- Name: string (nullable = true)
     |-- Value: string (nullable = true)
    
    +---------------+-----+
    |Name           |Value|
    +---------------+-----+
    |exp_Change_Rec |COL1 |
    |exp_Change_Rec |COL2 |
    |exp_Change_Rec |COL3 |
    |exp_Change_Rec |COL4 |
    |exp_Change_Flag|COL5 |
    |exp_Change_Flag|COL6 |
    |exp_Change_Flag|COL7 |
    +---------------+-----+
    

    【讨论】:

      【解决方案2】:

      爆炸多列的解决方案是使用

      df.select(explode(arrays_zip($"col1",$col2))).select( $"col.*").show(20,false)
      

      此解决方案从 2.4+ 开始提供

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-29
        • 2020-04-21
        • 1970-01-01
        • 2022-01-18
        • 2020-04-28
        相关资源
        最近更新 更多