如何在pyspark中创建数据框的副本?

问题描述 投票:5回答:2

我有一个数据框,通过执行以下操作,我需要通过该数据框创建一个新的数据帧,其中模式有一点变化。

>>> 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模块中的deepcopycopy方法 - 只需使用_X = X

copy方法失败并返回了

RecursionError: maximum recursion depth exceeded

赋值方法也不起作用

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

由于他们的id是相同的,创建一个重复的数据帧在这里并没有真正的帮助,在_X上完成的操作反映在X

所以我的问题确实是双重的

  • 如何更改架构(不对X进行任何更改)?
  • 更重要的是,如何创建pyspark数据帧的副本?

注意:

这个问题是对这个qazxsw poi的一个跟进

python apache-spark pyspark apache-spark-sql
2个回答
2
投票

正如在另一个问题的答案中所解释的那样,您可以对初始模式进行深度复制。然后我们可以修改该副本并使用它来初始化新的post 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,对象未在适当的位置更改,但会返回新副本。希望这可以帮助!


1
投票

在斯卡拉:

  1. 使用“X.schema.copy”创建新的模式实例,而不进行旧的模式修改;
  2. 在返回Dataframe(“select”,“where”等)的每个Dataframe操作中,创建新的Dataframe,而不修改原始数据。原件可以反复使用。猜猜看,你的案件不需要重复。性能是单独的问题,可以使用“持久性”。
© www.soinside.com 2019 - 2024. All rights reserved.