Spark unionAll несколько кадров данных
для набора кадров данных
val df1 = sc.parallelize(1 to 4).map(i => (i,i*10)).toDF("id","x")
val df2 = sc.parallelize(1 to 4).map(i => (i,i*100)).toDF("id","y")
val df3 = sc.parallelize(1 to 4).map(i => (i,i*1000)).toDF("id","z")
для объединения всех их я делаю
df1.unionAll(df2).unionAll(df3)
есть ли более элегантный и масштабируемый способ сделать это для любого количества таблиц данных, например,
Seq(df1, df2, df3)
2 ответов
самое простое решение -reduce
С union
(unionAll
в Spark
val dfs = Seq(df1, df2, df3)
dfs.reduce(_ union _)
это относительно лаконично и не должно перемещать данные из хранилища вне кучи но расширяет родословную с каждым Союзом требуется нелинейное время для выполнения анализа плана. что может быть проблемой, если вы попытаетесь объединить большое количество DataFrames
.
вы также можете конвертировать в RDDs
и использовать SparkContext.union
:
dfs match {
case h :: Nil => Some(h)
case h :: _ => Some(h.sqlContext.createDataFrame(
h.sqlContext.sparkContext.union(dfs.map(_.rdd)),
h.schema
))
case Nil => None
}
держит родословная short стоимость анализа низкая, но в остальном она менее эффективна, чем слияние DataFrames
напрямую.
для pyspark вы можете сделать следующее:
from functools import reduce
from pyspark.sql import DataFrame
dfs = [df1,df2,df3]
df = reduce(DataFrame.unionAll, dfs)
также ничего не стоит, чтобы порядок столбцов в кадрах данных был одинаковым для этого. Это может молча дать неожиданные результаты, если у вас нет правильных заказов столбцов!!
Если вы используете pyspark 2.3 или выше, вы можете использовать unionByName, поэтому вам не нужно переупорядочивать столбцы.