Scala isin在spark中的withcolumn函数中抛出stackoverflow错误
我在scala应用程序中使用spark 2.3。我有一个数据框架,它是从spark sql创建的,在我共享的示例代码中名为sqlDF。我有一个包含以下项目的字符串列表 列表[]字符串列表项 -9,-8,-7,-6 我想将dataframe中所有列中与此列表项匹配的所有值替换为0 初始数据帧Scala isin在spark中的withcolumn函数中抛出stackoverflow错误,scala,apache-spark,apache-spark-sql,Scala,Apache Spark,Apache Spark Sql,我在scala应用程序中使用spark 2.3。我有一个数据框架,它是从spark sql创建的,在我共享的示例代码中名为sqlDF。我有一个包含以下项目的字符串列表 列表[]字符串列表项 -9,-8,-7,-6 我想将dataframe中所有列中与此列表项匹配的所有值替换为0 初始数据帧 column1 | column2 | column3 1 |1 |1 2 |-5 |1 6 |-6 |1
column1 | column2 | column3
1 |1 |1
2 |-5 |1
6 |-6 |1
-7 |-8 |-7
它必须回到过去
column1 | column2 | column3
1 |1 |1
2 |-5 |1
6 |0 |1
0 |0 |0
为此,我在下面对sqlDF中的所有列(超过500列)进行查询
sqlDF = sqlDF.withColumn(currColumnName, when(col(currColumnName).isin(stringList:_*), 0).otherwise(col(currColumnName)))
但是得到下面的错误,顺便说一句,如果我只选择一列进行迭代,它会工作,但是如果我运行上面的代码进行500列迭代,它会失败
线程“streaming-job-executor-0”中出现异常
java.lang.StackOverflowerr位于
scala.collection.generic.GenTraversableFactory$GenericCanBuildFrom.apply(GenTraversableFactory.scala:57)
在
scala.collection.generic.GenTraversableFactory$GenericCanBuildFrom.apply(GenTraversableFactory.scala:52)
在
scala.collection.TraversableLike$class.builder$1(TraversableLike.scala:229)
在
scala.collection.TraversableLike$class.map(TraversableLike.scala:233)
位于scala.collection.immutable.List.map(List.scala:285)
org.apache.spark.sql.catalyst.trees.TreeNode$$anonfun$4.apply(TreeNode.scala:333)
在
org.apache.spark.sql.catalyst.trees.TreeNode.mapProductIterator(TreeNode.scala:187)
我遗漏了什么?我建议您播放字符串列表:
val stringList=sc.broadcast(<Your List of List[String]>)
确保您的currColumnName也是字符串格式。比较应该是字符串对字符串
foldLeft
非常适合您的情况,如下所示
val df = spark.sparkContext.parallelize(Seq(
(1, 1, 1),
(2, -5, 1),
(6, -6, 1),
(-7, -8, -7)
)).toDF("a", "b", "c")
val list = Seq(-7, -8, -9)
val resultDF = df.columns.foldLeft(df) { (acc, name) => {
acc.withColumn(name, when(col(name).isin(list: _*), 0).otherwise(col(name)))
}
}
输出:
+---+---+---+
|a |b |c |
+---+---+---+
|1 |1 |1 |
|2 |-5 |1 |
|6 |-6 |1 |
|0 |0 |0 |
+---+---+---+
+---+---+---+---+
| id| c1| c2| c3|
+---+---+---+---+
| 0| 1| 1| 1|
| 1| 2| -5| 1|
| 3| 0| 0| 0|
| 2| 6| 0| 1|
+---+---+---+---+
这里有一种不同的方法,在
columnX
和X
之间应用left anti-join
,其中X是传输到数据帧中的项目列表。左反联接将返回X
中不存在的所有项,我们通过外部联接将它们连接在一起的结果(可以用左联接替换以获得更好的性能,但这将排除所有零的记录,即id==3)基于单调递增的id分配的id:
import org.apache.spark.sql.functions.{单调递增的id,col}
val df=Seq(
(1, 1, 1),
(2, -5, 1),
(6, -6, 1),
(-7, -8, -7))
.toDF(“c1”、“c2”、“c3”)
.withColumn(“id”,单调递增的id())
val exdf=序列(-9,-8,-7,-6).toDF(“x”)
df.columns.map{c=>
df.选择(“id”,c).连接(exdf,col(c)==$“x”,“left\u anti”)
}
.reduce((df1,df2)=>df1.join(df2,Seq(“id”),“outer”))
.na.填充(0)
显示
输出:
+---+---+---+
|a |b |c |
+---+---+---+
|1 |1 |1 |
|2 |-5 |1 |
|6 |-6 |1 |
|0 |0 |0 |
+---+---+---+
+---+---+---+---+
| id| c1| c2| c3|
+---+---+---+---+
| 0| 1| 1| 1|
| 1| 2| -5| 1|
| 3| 0| 0| 0|
| 2| 6| 0| 1|
+---+---+---+---+
谢谢你的回复。但是迭代没有问题。foldLeft为我们提供迭代服务。当列大小大于500时,内部代码[withColumn(name,when(col(name).isin(list:*),0)。否则(col(name))]有问题。我使用for循环进行迭代,并将其切换到foldleft,但显然没有任何更改。