Zur Erinnerung, es gibt einen überraschend unbekannten Punkt bezüglich der vertikalen Verbindung von PySparks DataFrame.
Der Inhalt des Artikels basiert auf Spark 2.4.
Es gibt drei Arten von vertikalen Verbindungsmethoden für DataFrame.
Es gibt tatsächlich keinen induktiven Unterschied zwischen den beiden Methoden uniont und unionAll, die beide einfach vertikal zwei DataFrames verbinden.
Wenn Sie sich SQL vorstellen, ist es leicht zu missverstehen, dass die Duplizierungskontrolle in Union durchgeführt wird, aber in beiden Fällen wird keine Duplizierungskontrolle durchgeführt. Wenn eine doppelte Kontrolle erforderlich ist, muss daher nach der vertikalen Kopplung die Dinstinct-Methode verwendet werden.
In Version 2.0 und höher wird die Verwendung von Union empfohlen.
Union und UnionAll
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|
# +---+---+---+
Der Unterschied zwischen union und unionByName besteht darin, dass es sich beim vertikalen Verbinden auf den Spaltennamen des DataFrame bezieht.
union verbindet die ersten Spalten von zwei DataFrames, verbindet die zweiten Spalten usw. unter Berücksichtigung der Anordnung der Spalten im DataFrame. Mit anderen Worten, im Fall der Vereinigung wird der Spaltenname zum Zeitpunkt des Beitritts nicht angezeigt. Selbst wenn die DataFrames dieselben Spalten haben und die Reihenfolge unterschiedlich ist, werden sie basierend auf dem Spaltennamen des DataFrames, der die Methode aufgerufen hat, kombiniert, und diejenigen in derselben Spalte werden nicht kombiniert. Andererseits bezieht sich unionByName auf die Spaltennamen jedes DataFrame und verknüpft dieselben Spaltennamen.
Wenn die beiden zu kombinierenden DataFrames dasselbe Schema haben, ist es daher sicher, unionByName zu verwenden.
union und 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|
# +---+---+---+
Wenn beim vertikalen Verbinden von DataFrames die zu verbindenden Spaltentypen unterschiedlich sind, kann dies implizit umgewandelt werden. (Einige Muster verursachen einen Fehler, ohne dass dies getan wird.)
Selbst in der impliziten Umwandlung ist das Muster, in dem ein numerischer Typ wie Integer in einen String konvertiert wird, besonders problematisch, und es sollte beachtet werden, dass dies aufgrund von Unterschieden in der Behandlung von Flag-Werten ausreichend auftreten kann.
Hier wird das Beispiel der Vereinigung gezeigt, aber das gleiche gilt für unionByName (ich erkenne empirisch).
Zum Zeitpunkt der vertikalen Verbindung gegossen
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)
#Dies führt zu einem Fehler
# df.select('bool').union(df.select('str'))
Vertikal verbundene Methoden können nur das Verbinden von zwei DataFrames unterstützen. Wenn Sie 3 oder mehr DataFrames kombinieren möchten, können Sie Folgendes tun.
Vertikale Kombination mehrerer 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