Spark DataFrame添加带有行的列

时间:2017-02-04 14:35:12

标签: scala apache-spark apache-spark-sql spark-dataframe

向DataFrame添加新列和新行的最佳方法是什么? 是否可以同时执行此操作?

例如,我有一个表AB,如:

+------+-------+
|     a|      b|
+------+-------+
|  true|   true|      
|  true|  false|   
+---+---+------+

现在我想在AB和新行中添加一个新列“c”,但前提是满足条件。 这个条件应该适用于AB中的每一行,包括c = false和c = true。

foo(row): Boolean 成为条件并且:

foo(Row(true, true, false)) = true
foo(Row(true, true, true))  = true 
foo(Row(true, false, false)) = true 
foo(Row(true, false, false)) = false 

所以新表ABC应该是这样的:

  +------+-------+-------+
  |     a|      b|      c|
  +------+-------+-------+
  |  true|   true|   true|      
  |  true|   true|  false|      
  |  true|  false|  false|   
  +------+-------+-------+

我尝试交叉加入并过滤:

 val rows = List(Row(true), Row(false))

 val C = spark.createDataFrame(
     spark.sparkContext.parallelize(rows),
     StructType(List(StructField("c", BooleanType)))
 )

 val ABC = AB.join(C).filter(r => foo(row))

性能非常不好(你能告诉我为什么吗?)。我也试过flatMap:

      val encoder = RowEncoder(AB.schema.add(StructField("c", BooleanType)))

      val ABC = AB.flatMap { row =>
        Seq(Row.fromSeq(row.toSeq :+ true), Row.fromSeq(row.toSeq :+ false)).filter(r => foo(r))
      }(encoder)

表现也不错。大型桌子的铸造需要很长时间。正如我所注意到的那样,铸件应用于主节点。对于大型表(百万行),它表现不好。

对于这个问题,你有其他更好的解决方案吗?

顺便说一句,我正在使用带有Scala的Apache Spark 2.0.1。

1 个答案:

答案 0 :(得分:1)

我认为你已经让它变得比它需要的更复杂了,据我所知,以下应该会产生你想要的结果

val stuff = List[Row](Row(true, true),Row(true, false),Row(false, true), Row(false, false))
val rows = sc.parallelize(stuff)
val schema = StructType(StructField("a", BooleanType, true) :: StructField("b", BooleanType, true) :: Nil)
val frame = spark.createDataFrame(rows, schema).withColumn("c", col("a")&&(col("b")))

然后如果你做了frame.show,它应该显示

+-----+-----+-----+
|    a|    b|    c|
+-----+-----+-----+
| true| true| true|
| true|false|false|
|false| true|false|
|false|false|false|
+-----+-----+-----+