从变量字段为withColumn功能分配火花名称

时间:2018-09-29 11:16:09

标签: apache-spark apache-spark-sql

我有一些像下面这样的json数据,我需要根据一些Jason值创建新列

{“开始”:“ 1234567679”,“测试”:[“ abc”],“值”:324,“结束”:“ 1234567689”}

{“开始”:“ 1234567679”,“测试”:[“ xyz”],“值”:“附近”,“结束”:“ 1234567689”}

{“开始”:“ 1234568679”,“测试”:[“ pqr”],“值”:[“ Attr”,“”],“结束”:“ 1234568679”}}

{“开始”:“ 1234568997”,“测试”:[“ mno”],“值”:[“ {\”键\“:\” 1 \“,\”值\“:[\” 789 \“]}”],“ end”:“ 1234568999”}

上面是json示例

我想创建一个如下所示的列

 start      abc     xyz    pqr     mno    end
 1234567679 324     null   null    null   1234567689
 1234567889 null    Near   null    null   1234567989
 1234568679 null    null   attr    null   1234568679
 1234568997 null    null   null    789    1234568999

 def getValue1(s1: Seq[String], v: String) = {
      if (s1(0)=="abc"))  v else null
 } 

 def getValue2(s1: Seq[String], v: String) = {
     if (s1(0)=="xyz"))  v else null
 }  

 val df = spark.read.json("path to json")

 val tdf = df.withColumn("abc",getValue1($"test", $"value")).withColumn("xyz",getValue2($"test", $"value"))

但这是我不想使用的,因为我的测试值更多,我希望某些函数执行类似的操作

 def getColumnname(s1: Seq[String]) = {
    return s1(0)
 }  


 val tdf = df.withColumn(getColumnname($"test"),$"value"))

将值更改为列是否是个好主意,我想这样,因为我需要将其应用于需要普通列的某些机器学习代码中

1 个答案:

答案 0 :(得分:0)

您可以使用数据透视操作来执行此类操作。假设您在test列的数组中始终只有一项,这是更简单的解决方案;

import org.apache.spark.sql.functions._
val df = sqlContext.read.json("<yourPath>")
df.withColumn("test", $"test".getItem(0)).groupBy($"start", $"end").pivot("test").agg(first("value")).show
+----------+----------+----+----+
|     start|       end| abc| xyz|
+----------+----------+----+----+
|1234567679|1234567689| 324|null|
|1234567889|1234567689|null| 789|
+----------+----------+----+----+

如果test列中有多个值,则还可以使用explode函数;

df.withColumn("test", explode($"test")).groupBy($"start", $"end").pivot("test").agg(first("value")).show

有关更多信息:

希望对您有帮助!

更新我

根据您的评论和更新的问题,这是您需要遵循的解决方案。我已经 有意 分隔了所有操作,因此您可以轻松了解需要做哪些进一步的改进;

df.withColumn("value", regexp_replace($"value", "\\[", "")). //1
   withColumn("value", regexp_replace($"value", "\\]", "")). //2
   withColumn("value", split($"value", "\\,")).              //3
   withColumn("test", explode($"test")).                     //4
   withColumn("value", explode($"value")).                   //5
   withColumn("value", regexp_replace($"value", " +", "")).  //6
   filter($"value" !== "").                                  //7
   groupBy($"start", $"end").pivot("test").                  //8
   agg(first("value")).show                                  //9
  • 当您读取此类json文件时,它将为您提供一个数据框,其中的value列带有StringType。您无法直接将StringType转换为ArrayType,因此您需要执行第1、2、3行中的技巧,将其转换为ArrayType您可以一行执行这些操作,也可以仅使用一个正则表达式或定义udf。一切取决于您,,我只是想向您展示Apache Spark的功能。

  • 现在您在value列中有ArrayType。就像在第4行的test列中所做的那样,在第5行中展开该列。然后应用您的数据透视操作。