向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。
答案 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|
+-----+-----+-----+