Spark withColumn - 使用非Column类型变量添加列

时间:2018-04-06 23:06:36

标签: scala apache-spark

如何从变量值向数据框添加列?

我知道我可以使用.toDF(colName)创建数据框,.withColumn是添加列的方法。但是,当我尝试以下操作时,出现类型不匹配错误:

val myList = List(1,2,3)
val myArray = Array(1,2,3)

myList.toDF("myList")
  .withColumn("myArray", myArray)
  

类型不匹配,预期:列,实际:数组[Int]

此编译错误在myArray调用中的.withColumn上。如何将它从Array [Int]转换为Column类型?

2 个答案:

答案 0 :(得分:1)

错误消息具有正确的内容,您需要输入一个列(或lit())作为第二个参数withColumn()

试试这个

import org.apache.spark.sql.functions.typedLit

val myList = List(1,2,3)
val myArray = Array(1,2,3)

myList.toDF("myList")
  .withColumn("myArray", typedLit(myArray))

:)

答案 1 :(得分:0)

不确定withColumn是你真正想要的。您可以应用lit()使myArray符合方法规范,但结果将是DataFrame中每一行的相同数组值:

myList.toDF("myList").withColumn("myArray", lit(myArray)).
  show
// +------+---------+
// |myList|  myArray|
// +------+---------+
// |     1|[1, 2, 3]|
// |     2|[1, 2, 3]|
// |     3|[1, 2, 3]|
// +------+---------+

如果您尝试按列方式合并两个集合,则它与withColumn提供的变换不同。在这种情况下,您需要将每个转换为DataFrame并通过join进行组合。

现在,如果两个集合的元素是行标识并且在示例中彼此成对匹配,并且您希望以这种方式连接它们,则可以简单地加入转换后的DataFrame:

myList.toDF("myList").join(
    myArray.toSeq.toDF("myArray"), $"myList" === $"myArray"
  ).show
// +------+-------+
// |myList|myArray|
// +------+-------+
// |     1|      1|
// |     2|      2|
// |     3|      3|
// +------+-------+

但是如果两个集合具有不可连接的元素并且您只想按列合并它们,则需要使用两个数据帧中的兼容行标识列来连接它们。如果没有这样的行标识列,一种方法是创建自己的rowId,如下例所示:

import org.apache.spark.sql.Row
import org.apache.spark.sql.types._

val df1 = List("a", "b", "c").toDF("myList")
val df2 = Array("x", "y", "z").toSeq.toDF("myArray")

val rdd1 = df1.rdd.zipWithIndex.map{
  case (row: Row, id: Long) => Row.fromSeq(row.toSeq :+ id)
}
val df1withId = spark.createDataFrame( rdd1,
  StructType(df1.schema.fields :+ StructField("rowId", LongType, false))
)

val rdd2 = df2.rdd.zipWithIndex.map{
  case (row: Row, id: Long) => Row.fromSeq(row.toSeq :+ id)
}
val df2withId = spark.createDataFrame( rdd2, 
  StructType(df2.schema.fields :+ StructField("rowId", LongType, false))
)

df1withId.join(df2withId, Seq("rowId")).show
// +-----+------+-------+
// |rowId|myList|myArray|
// +-----+------+-------+
// |    0|     a|      x|
// |    1|     b|      y|
// |    2|     c|      z|
// +-----+------+-------+