3 回答
TA贡献1815条经验 获得超10个赞
对于这个用例,您可以使用pivot
:
ds
.withColumn("pivot_column", $"first_column")
.groupBy($"first_column")
.pivot("pivot_column")
.count
如果你想要更好的性能,你可能想在 pivot 中提供可能的值,比如pivot("pivot_column", Seq("a", "b", "c"))
我用于count聚合,但你可以进行任何你想要的聚合。
From
+------------+
|first_column|
+------------+
| a |
| b |
| c |
+------------+
To
+------------+---+---+---+
|first_column| a | b | c |
+------------+---+---+---+
| a | 1 | 0 | 0 |
| b | 0 | 1 | 0 |
| c | 0 | 0 | 1 |
+------------+---+---+---+
TA贡献1848条经验 获得超10个赞
如果的值Column是最小的/更少,请尝试下面的代码。
df.show
+------+
|Column|
+------+
| A|
| B|
| C|
+------+
// If you have multiple columns are exist, select only required column
val names = df.select($"Column").as[String].collect
val df1 = names.foldLeft(df)((df,n) => df.withColumn(n, lit(0)))
df1.show()
+------+---+---+---+
|Column| A| B| C|
+------+---+---+---+
| A| 0| 0| 0|
| B| 0| 0| 0|
| C| 0| 0| 0|
+------+---+---+---+
TA贡献1843条经验 获得超7个赞
我认为 Spark 的本质(更准确地说,它的并行性)不允许您使用 UDF 实现您的目标。
执行查询时,Spark 将数据分发给执行器,每个执行器都有自己的行块。每个行块都有自己的列的可能值列表Column
。因此,每个执行者都会尝试添加自己的列列表,这与其他执行者所做的不同。因此,当驱动程序尝试合并来自不同执行程序的结果集时,它会失败(或者执行程序可能会失败)。
collectAsList
确实解决了你的问题,虽然效率很低。
此外,您可以猜测列数并发明一些函数(适合您的实际数据)来将列获得的值映射Column
到这些数字 - 这样您就可以使每个执行程序的列集保持相等。该解决方案不是很通用,但可以解决某些情况。即,您会得到像这样的列:<c01, c02, c03, ..., cNN>
。
添加回答
举报