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

2024-05-22 02:42:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个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是相同的,因此在这里创建一个重复的数据帧并没有真正的帮助,对_X执行的操作反映在X中。

所以我的问题是

  • 如何更改模式输出(即不更改X)?

  • 更重要的是,如何创建pyspark数据帧的副本?

注意:

这个问题是这个post的后续问题


Tags: columns数据方法addiddataframenewschema
2条回答

在斯卡拉:

  1. 使用“X.schema.copy”创建新模式实例,而不修改旧模式
  2. 在每个返回Dataframe(“select”、“where”等)的Dataframe操作中,都会创建新的Dataframe,而不修改原始的Dataframe。原版可以反复使用。你的案子不需要复制。性能是单独的问题,可以使用“persist”。

正如在对另一个问题的回答中所解释的,您可以对初始模式进行深度复制。然后我们可以修改该副本并使用它初始化新的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添加一个新列时,对象不会就地更改,而是返回一个新副本。 希望这有帮助!

相关问题 更多 >