【问题标题】:Parse nested data using SCALA使用 SCALA 解析嵌套数据
【发布时间】:2017-11-13 11:41:33
【问题描述】:

我的数据框如下:

ColA  ColB     ColC  
1     [2,3,4] [5,6,7]

我需要把它转换成下面的

ColA ColB ColC  
1    2    5  
1    3    6  
1    4    7  

有人可以帮助编写 SCALA 中的代码吗?

【问题讨论】:

    标签: scala apache-spark


    【解决方案1】:

    您可以通过UDFexplode 压缩列来zip 两个数组列,如下所示:

    val df = Seq(
      (1, Seq(2, 3, 4), Seq(5, 6, 7))
    ).toDF("ColA", "ColB", "ColC")
    
    def zip = udf(
      (x: Seq[Int], y: Seq[Int]) => x zip y 
    )
    
    val df2 = df.select($"ColA", zip($"ColB", $"ColC").as("BzipC")).
      withColumn("BzipC", explode($"BzipC"))
    
    val df3 = df2.select($"ColA", $"BzipC._1".as("ColB"), $"BzipC._2".as("ColC"))
    
    df3.show
    +----+----+----+
    |ColA|ColB|ColC|
    +----+----+----+
    |   1|   2|   5|
    |   1|   3|   6|
    |   1|   4|   7|
    +----+----+----+
    

    【讨论】:

      【解决方案2】:

      我在这里提出的想法有点复杂,需要您使用map 来组合ColBColC 的两个数组。然后使用explode 函数来分解组合数组。最后将分解后的组合数组提取到不同的列。

      import org.apache.spark.sql.functions._
      val tempDF = df.map(row => {
        val colB = row(1).asInstanceOf[mutable.WrappedArray[Int]]
        val colC = row(2).asInstanceOf[mutable.WrappedArray[Int]]
        var array = Array.empty[(Int, Int)]
        for(loop <- 0 to colB.size-1){
          array = array :+ (colB(loop), colC(loop))
        }
        (row(0).asInstanceOf[Int], array)
      })
        .toDF("ColA", "ColB")
        .withColumn("ColD", explode($"ColB"))
      
      tempDF.withColumn("ColB", $"ColD._1").withColumn("ColC", $"ColD._2").drop("ColD").show(false)
      

      这会给你结果

      +----+----+----+
      |ColA|ColB|ColC|
      +----+----+----+
      |1   |2   |5   |
      |1   |3   |6   |
      |1   |4   |7   |
      +----+----+----+
      

      【讨论】:

        【解决方案3】:

        您还可以使用 HiveQL 中的 posexplodelateral view 的组合

        sqlContext.sql(""" 
        select 1 as colA, array(2,3,4) as colB, array(5,6,7) as colC 
        """).registerTempTable("test")
        
        sqlContext.sql(""" 
        select 
            colA , b as colB, c as colC 
        from 
            test 
        lateral view 
            posexplode(colB) columnB as seqB, b 
        lateral view 
            posexplode(colC) columnC as seqC, c 
        where 
            seqB = seqC 
        """ ).show
        
        +----+----+----+
        |colA|colB|colC|
        +----+----+----+
        |   1|   2|   5|
        |   1|   3|   6|
        |   1|   4|   7|
        +----+----+----+
        

        致谢:https://stackoverflow.com/a/40614822/7224597 ;)

        【讨论】:

          猜你喜欢
          • 2018-10-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多