J'ai une trame de données à partir de laquelle je dois créer une nouvelle trame de données avec un petit changement dans le schéma en effectuant l'opération suivante.
>>> 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)
Le problème est que dans l'opération ci-dessus, le schéma de X
est modifié en place. Donc, quand j'imprime X.columns
Je reçois
>>> X.columns
['a', 'b', 'id_col']
mais les valeurs dans X
sont toujours les mêmes
>>> X.show()
+---+---+
| a| b|
+---+---+
| 1| 2|
| 3| 4|
+---+---+
Pour éviter de modifier le schéma de X
, j'ai essayé de créer une copie de X
de trois manières - en utilisant les méthodes copy
et deepcopy
à partir des copy
module - en utilisant simplement _X = X
Les méthodes copy
ont échoué et renvoyé un
RecursionError: maximum recursion depth exceeded
La méthode d'affectation ne fonctionne pas non plus
>>> _X = X
>>> id(_X) == id(X)
True
Étant donné que leurs id
sont les mêmes, la création d'une trame de données en double n'aide pas vraiment ici et les opérations effectuées sur _X
se reflète dans X
.
Donc ma question est vraiment double
comment changer la place du schéma (c'est-à-dire sans apporter de modifications à X
)?
et plus important encore, comment créer un doublon d'une trame de données pyspark?
Remarque:
Cette question fait suite à cette post
Comme expliqué dans la réponse à l'autre question, vous pouvez faire une copie profonde de votre schéma initial. Nous pouvons ensuite modifier cette copie et l'utiliser pour initialiser le nouveau 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)
Voyons maintenant:
print('Schema of X: ' + str(X.schema))
print('Schema of _X: ' + str(_X.schema))
Sortie:
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)))
Notez que pour copier un DataFrame
, vous pouvez simplement utiliser _X = X
. Chaque fois que vous ajoutez une nouvelle colonne avec par exemple withColumn
, l'objet n'est pas modifié en place, mais une nouvelle copie est retournée. J'espère que cela t'aides!
À Scala: