如何在pyspark中创建 Dataframe 的副本?

disbfnqx  于 2023-01-08  发布在  Spark
关注(0)|答案(5)|浏览(276)

我有一个 Dataframe ,我需要通过执行以下操作在模式中做一个小的更改来创建一个新的 Dataframe 。

>>> X = spark.createDataFrame([[1,2], [3,4]], ['a', 'b'])
>>> schema_new = X.schema.add('id_col', LongType(), False)
>>> _X = X.rdd.zipWithIndex().map(lambda l: list(l[0]) + [l[1]]).toDF(schema_new)

问题是,在上面的操作中,X的模式在原处被改变了,所以当我打印X.columns时,我得到

>>> X.columns
['a', 'b', 'id_col']

但是X中的值仍然相同

>>> X.show()
+---+---+
|  a|  b|
+---+---+
|  1|  2|
|  3|  4|
+---+---+

为了避免更改X的模式,我尝试使用三种方法创建X的副本-使用copy模块中的copydeepcopy方法-仅使用_X = X
copy方法失败并返回

RecursionError: maximum recursion depth exceeded

赋值方法也不起作用

>>> _X = X
>>> id(_X) == id(X)
True

由于它们的id是相同的,因此创建重复的 Dataframe 在这里实际上没有帮助,并且在_X上完成的操作反映在X中。
所以我的问题有两个

  • 如何将模式更改为outplace(即不对X进行任何更改)?
  • 更重要的是,如何创建pyspark Dataframe 的副本?
    • 注:**

此问题是此post的后续问题

vybvopom

vybvopom1#

.alias()通常用于重命名列,但它也是一个DataFrame方法,可以给予您想要的内容:

df2 = df.alias('df2')
id(df2) == id(df)  # False
mcvgt66p

mcvgt66p2#

正如在对另一个问题的回答中所解释的,你可以创建一个初始模式的深副本,然后我们可以修改这个副本,并使用它来初始化新的DataFrame_X

import pyspark.sql.functions as F
from pyspark.sql.types import LongType
import copy

X = spark.createDataFrame([[1,2], [3,4]], ['a', 'b'])
_schema = copy.deepcopy(X.schema)
_schema.add('id_col', LongType(), False) # modified inplace
_X = X.rdd.zipWithIndex().map(lambda l: list(l[0]) + [l[1]]).toDF(_schema)

现在让我们检查:

print('Schema of X: ' + str(X.schema))
print('Schema of _X: ' + str(_X.schema))

输出:

Schema of X: StructType(List(StructField(a,LongType,true),StructField(b,LongType,true)))
Schema of _X: StructType(List(StructField(a,LongType,true),
                  StructField(b,LongType,true),StructField(id_col,LongType,false)))

请注意,要复制DataFrame,您可以只使用_X = X。每当您使用withColumn添加一个新列时,对象不会在原处更改,而是返回一个新副本。希望这对您有所帮助!

u0njafvf

u0njafvf3#

如果您需要创建一个pyspark Dataframe 的副本,您可以使用Pandas(如果您的用例允许的话)。

schema = X.schema
X_pd = X.toPandas()
_X = spark.createDataFrame(X_pd,schema=schema)
del X_pd
kiayqfof

kiayqfof4#

在Scala中:
1.使用“X.schema.copy”创建新模式示例,而不修改旧模式;
1.在每个返回Dataframe(“select”、“where”等)的Dataframe操作中,将创建新的Dataframe,而不修改原始数据。原始数据可以反复使用。猜猜看,您的情况不需要复制。性能是单独的问题,可以使用“persist”。

wn9m85ua

wn9m85ua5#

df2 = df.select("*")
id(df2) = id(df)  # False

这与@SantiagoRodriguez给出的答案相同,也代表了与@tozCSS共享的类似方法。我相信@tozCSS使用.alias()代替.select()的建议可能确实是最有效的。

相关问题