[PYTHON] Remarques et conseils sur l'assemblage vertical de PySpark DataFrame

introduction

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.

Connexion verticale de PySpark

À propos de la différence entre les méthodes verticalement connectées

Il existe trois types de méthodes de connexion verticale pour DataFrame.

Différence entre union et union Tous

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|
# +---+---+---+

Différence entre union et unionByName

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|
# +---+---+---+

À propos de Cast au moment de l'adhésion

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'))

À propos de la connexion verticale de plusieurs DataFrames

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

Remarques et conseils sur l'assemblage vertical de PySpark DataFrame
Remarques sur tf.function et traçage
Remarques sur les * args et ** kargs
Notes sur pyenv et Atom
Introduction et astuces de mlflow.
Notes sur Python et les types de dictionnaire
Remarques sur l'utilisation de la post-réception et de la post-fusion
Remarques sur l'entrée / sortie standard de Go
Remarques sur la construction de Python et pyenv sur Mac
Remplissez la valeur manquante (null) de DataFrame avec les valeurs avant et après avec pyspark
Remarques sur l'installation de Python3 et l'utilisation de pip sous Windows7
Fonctionnement de base de Python Pandas Series et Dataframe (1)