Как я могу эффективно добавить несколько столбцов в Spark Datframe - PullRequest
2 голосов
/ 20 июня 2020

У меня есть набор имен столбцов, и мне нужно добавить эти столбцы в существующий фрейм данных, который также очень большой по размеру, мне нужно добавить все столбцы из набора в фрейм данных с StringType и значением null по умолчанию. Я следую приведенному ниже подходу, но обнаружил, что когда количество столбцов и размер фрейма данных огромны, это влияет на мою производительность. Есть ли лучший способ сделать это в Spark? Примечание: количество столбцов: ~ 500

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)
+---+----------+
|Id |Name      |
+---+----------+
|1  |James     |
|2  |Michael   |
|3  |Robert    |
|4  |Washington|
|5  |Jefferson |
+---+----------+

+---+----------+----+----+----+-----+----+-----+----+-----+-----+-----+-----+----+-----+----+----+-----+-----+-----+-----+-----+----+-----+
|Id |Name      |col7|col8|col3|col17|col6|col20|col2|col14|col16|col21|col15|col9|col10|col5|col1|col13|col19|col11|col22|col18|col4|col12|
+---+----------+----+----+----+-----+----+-----+----+-----+-----+-----+-----+----+-----+----+----+-----+-----+-----+-----+-----+----+-----+
|1  |James     |null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
|2  |Michael   |null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
|3  |Robert    |null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
|4  |Washington|null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
|5  |Jefferson |null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
+---+----------+----+----+----+-----+----+-----+----+-----+-----+-----+-----+----+-----+----+----+-----+-----+-----+-----+-----+----+-----+

Ответы [ 2 ]

2 голосов
/ 20 июня 2020

Используйте select

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 |
+---+----------+
scala> 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
scala> 

diff_set
.foldLeft(df)((ddf,c) => 
    ddf
    .withColumn(c,lit(null).cast("string"))
)
.show(false)

+---+----------+----+----+----+-----+----+-----+----+-----+-----+-----+-----+----+-----+----+----+-----+-----+-----+-----+-----+----+-----+
|Id |Name      |col7|col8|col3|col17|col6|col20|col2|col14|col16|col21|col15|col9|col10|col5|col1|col13|col19|col11|col22|col18|col4|col12|
+---+----------+----+----+----+-----+----+-----+----+-----+-----+-----+-----+----+-----+----+----+-----+-----+-----+-----+-----+----+-----+
|1  |James     |null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
|2  |Michael   |null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
|3  |Robert    |null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
|4  |Washington|null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
|5  |Jefferson |null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
+---+----------+----+----+----+-----+----+-----+----+-----+-----+-----+-----+----+-----+----+----+-----+-----+-----+-----+-----+----+-----+

Сравнение

Используя foldLeft для 1000000 записей - Затраченное время: 18017 мс

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)
}

Использование crossJoin для 1000000 записей - Затраченное время: 13224 мс

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)
}

Использование select для 1000000 записей - Затраченное время: 8519 мс

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
}
0 голосов
/ 22 июня 2020

Итак, это в PySpark.

df.select(
    '*', 
    *list(F.lit(None).alias(f'col{n}') for n in range(7,13))
).show()
+---+----------+----+----+----+-----+----+-----+----+-----+-----+-----+-----+----+-----+----+----+-----+-----+-----+-----+-----+----+-----+
|Id |Name      |col7|col8|col3|col17|col6|col20|col2|col14|col16|col21|col15|col9|col10|col5|col1|col13|col19|col11|col22|col18|col4|col12|
+---+----------+----+----+----+-----+----+-----+----+-----+-----+-----+-----+----+-----+----+----+-----+-----+-----+-----+-----+----+-----+
|1  |James     |null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
|2  |Michael   |null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
|3  |Robert    |null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
|4  |Washington|null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
|5  |Jefferson |null|null|null|null |null|null |null|null |null |null |null |null|null |null|null|null |null |null |null |null |null|null |
+---+----------+----+----+----+-----+----+-----+----+-----+-----+-----+-----+----+-----+----+----+-----+-----+-----+-----+-----+----+-----+

Этот logi c переводится в Scala spark, если вы понимаете, как заменить понимание списка в Scala на карту.

Это быстрее, поскольку он создает 22 столбца для одновременного выполнения, а не добавляет их в итерациях, как это делает foldleft.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...