Pour rappel, il existe un point étonnamment inconnu concernant la connexion verticale du DataFrame de PySpark.
Le contenu de l'article est basé sur Spark 2.4.
Il existe trois types de méthodes de connexion verticale pour DataFrame.
Il n'y a en fait aucune différence inductive entre les deux méthodes, uniont et unionAll, qui joignent simplement verticalement deux DataFrames.
Si vous imaginez SQL, il est facile de mal comprendre que le contrôle de duplication est effectué en union, mais dans les deux cas, le contrôle de duplication n'est pas effectué. Par conséquent, si un contrôle en double est nécessaire, il est nécessaire d'utiliser la méthode dinstinct après couplage vertical.
Dans la version 2.0 et supérieure, l'utilisation de l'union est recommandée.
union et unionTous
df1 = spark.createDataFrame([(1, 2, 3), (4, 5, 6)], ['x', 'y', 'z'])
df2 = spark.createDataFrame([(4, 5, 6), (7, 8, 9)], ['x', 'y', 'z'])
df_union = df1.union(df2)
df_unionAll = df1.unionAll(df2)
print('df1')
df1.show()
print('df2')
df2.show()
# df1
# +---+---+---+
# | x| y| z|
# +---+---+---+
# | 1| 2| 3|
# | 4| 5| 6|
# +---+---+---+
#
# df2
# +---+---+---+
# | x| y| z|
# +---+---+---+
# | 4| 5| 6|
# | 7| 8| 9|
# +---+---+---+
print('union')
df_union.show()
print('unionAll')
df_unionAll.show()
# union
# +---+---+---+
# | x| y| z|
# +---+---+---+
# | 1| 2| 3|
# | 4| 5| 6|
# | 4| 5| 6|
# | 7| 8| 9|
# +---+---+---+
#
# unionAll
# +---+---+---+
# | x| y| z|
# +---+---+---+
# | 1| 2| 3|
# | 4| 5| 6|
# | 4| 5| 6|
# | 7| 8| 9|
# +---+---+---+
La différence entre union et unionByName est qu'il fait référence au nom de colonne du DataFrame lors de la jointure verticale.
union joint les premières colonnes de deux DataFrames, joint les secondes colonnes, et ainsi de suite, en tenant compte de la disposition des colonnes dans le DataFrame. En d'autres termes, dans le cas d'union, le nom de la colonne n'est pas vu au moment de la jonction. Même si les DataFrames ont les mêmes colonnes, si l'ordre est différent, ils seront combinés en fonction du nom de colonne du DataFrame qui a appelé la méthode, et ceux de la même colonne ne seront pas combinés. D'autre part, unionByName fait référence aux noms de colonne de chaque DataFrame et joint les mêmes noms de colonne.
Par conséquent, si les deux DataFrames que vous souhaitez combiner ont le même schéma, vous pouvez utiliser unionByName en toute sécurité.
union et unionByName
df1 = spark.createDataFrame([(1, 2, 3)], ['x', 'y', 'z'])
df2 = spark.createDataFrame([(4, 5, 6)], ['z', 'x', 'y'])
df_union = df1.union(df2)
df_unionByName = df1.unionByName(df2)
print('df1')
df1.show()
print('df2')
df2.show()
# df1
# +---+---+---+
# | x| y| z|
# +---+---+---+
# | 1| 2| 3|
# +---+---+---+
#
# df2
# +---+---+---+
# | z| x| y|
# +---+---+---+
# | 4| 5| 6|
# +---+---+---+
print('union')
df_union.show()
print('unionByName')
df_unionByName.show()
# union
# +---+---+---+
# | x| y| z|
# +---+---+---+
# | 1| 2| 3|
# | 4| 5| 6|
# +---+---+---+
#
# unionByName
# +---+---+---+
# | x| y| z|
# +---+---+---+
# | 1| 2| 3|
# | 5| 6| 4|
# +---+---+---+
Lors de la jonction verticale de DataFrames, si les types de colonnes à joindre sont différents, il peut être implicitement converti. (Certains modèles provoquent une erreur sans être fait)
Même dans le Cast implicite, le modèle dans lequel un type numérique tel que Integer est converti en String est particulièrement gênant, et il convient de noter que cela peut se produire suffisamment en raison des différences dans la gestion des valeurs d'indicateur.
Ici, un exemple d'union est montré, mais il en va de même pour unionByName (je reconnais empiriquement).
Coulé au moment de la connexion verticale
from pyspark.sql.functions import col
from pyspark.sql.types import *
df = spark.createDataFrame([(1, 'x', True)], ['long', 'str', 'bool']).withColumn('int', col('long').cast('int'))
df.show()
df.printSchema()
# +------+---+----+---+
# |bigint|str|bool|int|
# +------+---+----+---+
# | 1| x|true| 1|
# +------+---+----+---+
# root
# |-- bigint: long (nullable = true)
# |-- str: string (nullable = true)
# |-- bool: boolean (nullable = true)
# |-- int: integer (nullable = true)
df.select('int').union(df.select('str')).printSchema()
# root
# |-- int: string (nullable = true)
df.select('int').union(df.select('long')).printSchema()
# root
# |-- int: long (nullable = true)
#Cela entraînera une erreur
# df.select('bool').union(df.select('str'))
Les méthodes jointes verticalement ne peuvent prendre en charge que la jonction de deux DataFrames. Si vous souhaitez combiner 3 DataFrames ou plus, vous pouvez effectuer les opérations suivantes.
Combinaison verticale de plusieurs DataFrames
from functools import reduce
from pyspark.sql import DataFrame
df1 = spark.createDataFrame([(1, 2, 3)], ['x', 'y', 'z'])
df2 = spark.createDataFrame([(4, 5, 6)], ['x', 'y', 'z'])
df3 = spark.createDataFrame([(7, 8, 9)], ['x', 'y', 'z'])
df = reduce(DataFrame.unionByName, [df1, df2, df3])
df.show()
# +---+---+---+
# | x| y| z|
# +---+---+---+
# | 1| 2| 3|
# | 4| 5| 6|
# | 7| 8| 9|
# +---+---+---+
Recommended Posts