Dataframe 如何在Spark Datframe中高效地添加多个列
我有一组列名称,需要在现有的dataframe中添加这些列,而dataframe的大小也非常大,我需要使用StringType和默认空值将所有列从集合添加到dataframe。 我遵循下面的方法,但我发现当列数和数据帧大小很大时,这会影响我的性能。在spark有没有更好的方法? 注:列数:~500Dataframe 如何在Spark Datframe中高效地添加多个列,dataframe,apache-spark,apache-spark-sql,Dataframe,Apache Spark,Apache Spark Sql,我有一组列名称,需要在现有的dataframe中添加这些列,而dataframe的大小也非常大,我需要使用StringType和默认空值将所有列从集合添加到dataframe。 我遵循下面的方法,但我发现当列数和数据帧大小很大时,这会影响我的性能。在spark有没有更好的方法? 注:列数:~500 import sparkSession.sqlContext.implicits._ var df = Seq( (1, "James"), (2, "Micha
import sparkSession.sqlContext.implicits._
var df = Seq(
(1, "James"),
(2, "Michael"),
(3, "Robert"),
(4, "Washington"),
(5, "Jefferson")
).toDF("Id", "Name")
df.show(false)
val diff_set = Seq("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10", "col11", "col12", "col13", "col14", "col15", "col16", "col17", "col18", "col19", "col20", "col21", "col22").toSet
diff_set.foreach(x => {
if (x.size > 0) {
df = df.withColumn(x, lit(null)).withColumn(x, col(x).cast(StringType))
}
})
df.show(false)
使用
选择
df
.select(
df.columns.map(c => col(c).as(c)) ++
diff_set.map(c => lit(null).cast("string").as(c)):_*
)
.show(false)
使用foldLeft
scala> df.show(false)
+---+----------+
|Id |Name |
+---+----------+
|1 |James |
|2 |Michael |
|3 |Robert |
|4 |Washington|
|5 |Jefferson |
+---+----------+
比较
对1000000
记录使用foldLeft
-所用时间:18017 ms
spark.time {
val diff_set = Seq("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10", "col11", "col12", "col13", "col14", "col15", "col16", "col17", "col18", "col19", "col20", "col21", "col22").toSet
val df = (1 to 1000000).toDF
diff_set.foldLeft(df)((ddf,c) => ddf.withColumn(c,lit(null).cast("string"))).show(false)
}
spark.time {
val diff_set = Seq("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10", "col11", "col12", "col13", "col14", "col15", "col16", "col17", "col18", "col19", "col20", "col21", "col22").toSet
val df = (1 to 1000000).toDF
val dfb = Seq(("null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null")).toDF(diff_set.toList:_*)
df.crossJoin(dfb).show(false)
}
spark.time {
val diff_set = Seq("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10", "col11", "col12", "col13", "col14", "col15", "col16", "col17", "col18", "col19", "col20", "col21", "col22").toSet
val df = (1 to 1000000).toDF
df.select(df.columns.map(c => col(c).as(c)) ++ diff_set.map(c => lit(null).cast("string").as(c)):_*).show
}
对1000000
记录使用crossJoin
-所用时间:13224 ms
spark.time {
val diff_set = Seq("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10", "col11", "col12", "col13", "col14", "col15", "col16", "col17", "col18", "col19", "col20", "col21", "col22").toSet
val df = (1 to 1000000).toDF
diff_set.foldLeft(df)((ddf,c) => ddf.withColumn(c,lit(null).cast("string"))).show(false)
}
spark.time {
val diff_set = Seq("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10", "col11", "col12", "col13", "col14", "col15", "col16", "col17", "col18", "col19", "col20", "col21", "col22").toSet
val df = (1 to 1000000).toDF
val dfb = Seq(("null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null")).toDF(diff_set.toList:_*)
df.crossJoin(dfb).show(false)
}
spark.time {
val diff_set = Seq("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10", "col11", "col12", "col13", "col14", "col15", "col16", "col17", "col18", "col19", "col20", "col21", "col22").toSet
val df = (1 to 1000000).toDF
df.select(df.columns.map(c => col(c).as(c)) ++ diff_set.map(c => lit(null).cast("string").as(c)):_*).show
}
使用为1000000
记录选择-所用时间:8519 ms
spark.time {
val diff_set = Seq("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10", "col11", "col12", "col13", "col14", "col15", "col16", "col17", "col18", "col19", "col20", "col21", "col22").toSet
val df = (1 to 1000000).toDF
diff_set.foldLeft(df)((ddf,c) => ddf.withColumn(c,lit(null).cast("string"))).show(false)
}
spark.time {
val diff_set = Seq("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10", "col11", "col12", "col13", "col14", "col15", "col16", "col17", "col18", "col19", "col20", "col21", "col22").toSet
val df = (1 to 1000000).toDF
val dfb = Seq(("null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null", "null")).toDF(diff_set.toList:_*)
df.crossJoin(dfb).show(false)
}
spark.time {
val diff_set = Seq("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10", "col11", "col12", "col13", "col14", "col15", "col16", "col17", "col18", "col19", "col20", "col21", "col22").toSet
val df = (1 to 1000000).toDF
df.select(df.columns.map(c => col(c).as(c)) ++ diff_set.map(c => lit(null).cast("string").as(c)):_*).show
}
所以这是Pypark
df.select(
'*',
*list(F.lit(None).alias(f'col{n}') for n in range(7,13))
).show()
如果您了解如何用map替换Scala中的列表理解,那么这个逻辑将转换为Scala spark
这比foldleft那样在迭代中添加22列更快,因为它一次创建要执行的22列。感谢@Srinivas:)使用select
approach性能显著提高。我还了解了spark.time{}
函数:)