克隆/深度复制Spark DataFrame

时间:2019-07-15 21:01:33

标签: apache-spark apache-spark-sql

如何请求DataFrame的深拷贝-而无需完全重新计算原始DataFrame内容?

目的是在Spark Stream上执行自联接。

2 个答案:

答案 0 :(得分:1)

数据帧是不可变的。这意味着您不必执行深层复制,您可以多次重复使用它们,并且在每次操作时都会创建新的数据框,而原始数据将保持不变。

例如:

val df = List((1),(2),(3)).toDF("id")

val df1 = df.as("df1") //second dataframe
val df2 = df.as("df2") //third dataframe

df1.join(df2, $"df1.id" === $"df2.id") //fourth dataframe and df is still unmodified

这似乎是对资源的浪费,但是由于数据框中的所有数据也是不可变的,因此所有四个数据框都可以重用对其中的对象的引用。

答案 1 :(得分:1)

常用方法:

    val asdfDF = Seq((1, "a"), (2, "b"), (3, "c")).toDF("id", "text")
    val columns = asdfDF.schema.fields.map(_.name).toSeq
    val column0 = columns.head
    val columnsRest = columns.tail
    val columnTemp = column0 + UUID.randomUUID().toString
    val asdfDF2 = asdfDF
      .withColumn(columnTemp, col(column0))
      .drop(column0)
      .withColumnRenamed(columnTemp, column0)
      .select(column0, columnsRest: _*)
    asdfDF
      .join(asdfDF2,
        asdfDF("id") === (asdfDF2("id") - 1)
        , "inner")
      .show()

简短替代:

    val asdfDF = Seq(1, 2, 3).toDF("id")
    val asdfDF2 = asdfDF
      .withColumn("id2", $"id")
      .select($"id2".as("id"))
    asdfDF
      .join(asdfDF2,
        asdfDF("id") === (asdfDF2("id") - 1)
        , "inner")
      .show()

此代码产生以下输出:

+---+----+---+----+
| id|text| id|text|
+---+----+---+----+
|  1|   a|  2|   b|
|  2|   b|  3|   c|
+---+----+---+----+