我有一个数据框,通过执行以下操作,我需要通过该数据框创建一个新的数据帧,其中模式有一点变化。
>>> 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
模块中的deepcopy
和copy
方法 - 只需使用_X = X
copy
方法失败并返回了
RecursionError: maximum recursion depth exceeded
赋值方法也不起作用
>>> _X = X
>>> id(_X) == id(X)
True
由于他们的id
是相同的,创建一个重复的数据帧在这里并没有真正的帮助,在_X
上完成的操作反映在X
。
所以我的问题确实是双重的
X
进行任何更改)?注意:
这个问题是对这个qazxsw poi的一个跟进
正如在另一个问题的答案中所解释的那样,您可以对初始模式进行深度复制。然后我们可以修改该副本并使用它来初始化新的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
,对象未在适当的位置更改,但会返回新副本。希望这可以帮助!
在斯卡拉: