Apache spark spark从变量字段为withColumn函数指定列名

Apache spark spark从变量字段为withColumn函数指定列名,apache-spark,apache-spark-sql,Apache Spark,Apache Spark Sql,我有一些json数据,如下所示,我需要基于一些Jason值创建新列 {“开始”:“1234567679”,“测试”:[“abc”],“值”:324,“结束”:“1234567689”} {“开始”:“1234567679”,“测试”:[“xyz”],“值”:“接近”,“结束”:“1234567689”} {“开始”:“1234568679”,“测试”:[“pqr”],“值”:[“Attr”,“”],“结束”:“1234568679”} {“开始”:“1234568997”,“测试”:[“mno”

我有一些json数据,如下所示,我需要基于一些Jason值创建新列

{“开始”:“1234567679”,“测试”:[“abc”],“值”:324,“结束”:“1234567689”}
{“开始”:“1234567679”,“测试”:[“xyz”],“值”:“接近”,“结束”:“1234567689”}
{“开始”:“1234568679”,“测试”:[“pqr”],“值”:[“Attr”,“”],“结束”:“1234568679”}
{“开始”:“1234568997”,“测试”:[“mno”],“值”:[“{\”键\“:\”1\”,“值\“:[\”789\“]}],“结束”:“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(“json路径”)
val tdf=df.withColumn(“abc”,getValue1($“test”,$“value”))。withColumn(“xyz”,getValue2($“test”,$“value”))
但是我不想用这个,因为我的测试值更多,我想要一些函数做类似的事情

def getColumnname(s1:Seq[String])={
返回s1(0)
}  
val tdf=df.withColumn(getColumnname($“test”),$“value”))

将值更改为列是一个好主意吗?我希望这样,因为我需要将其应用到一些需要普通列的机器学习代码上

您可以使用pivot操作来执行这些操作。假设数组中总是有一个项用于
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|
+----------+----------+----+----+
有关更多信息:

我希望有帮助

更新一 根据您的评论和更新的问题,以下是您需要遵循的解决方案。我有意地将所有操作分离开来,这样您就可以很容易地了解需要做什么来进一步改进

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
    。在第5行中分解此列,就像我们在第4行中对
    test
    列所做的那样。然后应用旋转操作


您好,在我的数据中还观察到一个奇怪的字段,值字段并不总是int,有时是字符串、数组等。。{“开始”:“1234567679”,“测试”:[“abc”],“值”:324,“结束”:“1234567689”}{“开始”:“1234567679”,“测试”:“xyz”],“值”:“近”,“结束”:“1234567689”}{“开始”:“1234567679”,“测试”:[“pqr”],“值”:[“列表”,“结束”:“1234567689”}嗨,我在json中的值字段中又找到了一种类型,我只想从json中提取value字段
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