Wie ich in Spark Dataframe weiß, kann dieser für mehrere Spalten denselben Namen haben, wie im folgenden Datenrahmen-Snapshot gezeigt:
[
Row(a=107831, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0}), a=107831, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0})),
Row(a=107831, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0}), a=125231, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0047, 3: 0.0, 4: 0.0043})),
Row(a=107831, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0}), a=145831, f=SparseVector(5, {0: 0.0, 1: 0.2356, 2: 0.0036, 3: 0.0, 4: 0.4132})),
Row(a=107831, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0}), a=147031, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0})),
Row(a=107831, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0}), a=149231, f=SparseVector(5, {0: 0.0, 1: 0.0032, 2: 0.2451, 3: 0.0, 4: 0.0042}))
]
Das obige Ergebnis wird durch Verknüpfen mit einem Datenrahmen zu sich selbst erstellt. Sie können sehen, dass 4
Spalten mit zwei a
und vorhanden sind f
.
Das Problem ist, dass ich dort bin, wenn ich versuche, mehr Berechnungen mit der a
Spalte durchzuführen. Ich kann keine Möglichkeit finden, die auszuwählen a
. Ich habe es versucht df[0]
und df.select('a')
beide haben mich unter Fehlermeldung zurückgegeben:
AnalysisException: Reference 'a' is ambiguous, could be: a#1333L, a#1335L.
Gibt es in der Spark-API überhaupt eine Möglichkeit, die Spalten wieder von den duplizierten Namen zu unterscheiden? oder vielleicht eine Möglichkeit, die Spaltennamen zu ändern?
'
Kurzschrift für die Spaltenauswahl, sodass es in der Tat kein Problem mit Anführungszeichen gibt.python
und markiert istpyspark
.df1.withColumnRenamed("a", "df1_a")
Beginnen wir mit einigen Daten:
from pyspark.mllib.linalg import SparseVector from pyspark.sql import Row df1 = sqlContext.createDataFrame([ Row(a=107831, f=SparseVector( 5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0})), Row(a=125231, f=SparseVector( 5, {0: 0.0, 1: 0.0, 2: 0.0047, 3: 0.0, 4: 0.0043})), ]) df2 = sqlContext.createDataFrame([ Row(a=107831, f=SparseVector( 5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0})), Row(a=107831, f=SparseVector( 5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0})), ])
Es gibt verschiedene Möglichkeiten, wie Sie dieses Problem angehen können. Zunächst können Sie untergeordnete Spalten mit übergeordneten Spalten eindeutig referenzieren:
df1.join(df2, df1['a'] == df2['a']).select(df1['f']).show(2) ## +--------------------+ ## | f| ## +--------------------+ ## |(5,[0,1,2,3,4],[0...| ## |(5,[0,1,2,3,4],[0...| ## +--------------------+
Sie können auch Tabellenaliasnamen verwenden:
from pyspark.sql.functions import col df1_a = df1.alias("df1_a") df2_a = df2.alias("df2_a") df1_a.join(df2_a, col('df1_a.a') == col('df2_a.a')).select('df1_a.f').show(2) ## +--------------------+ ## | f| ## +--------------------+ ## |(5,[0,1,2,3,4],[0...| ## |(5,[0,1,2,3,4],[0...| ## +--------------------+
Schließlich können Sie Spalten programmgesteuert umbenennen:
df1_r = df1.select(*(col(x).alias(x + '_df1') for x in df1.columns)) df2_r = df2.select(*(col(x).alias(x + '_df2') for x in df2.columns)) df1_r.join(df2_r, col('a_df1') == col('a_df2')).select(col('f_df1')).show(2) ## +--------------------+ ## | f_df1| ## +--------------------+ ## |(5,[0,1,2,3,4],[0...| ## |(5,[0,1,2,3,4],[0...| ## +--------------------+
quelle
df2_r = **df2** .select(*(col(x).alias(x + '_df2') for x in df2.columns))
stattdf2_r = df1.select(*(col(x).alias(x + '_df2') for x in df2.columns))
. Im Übrigen gute SachenEs gibt einen einfacheren Weg als Aliase für alle Spalten zu schreiben, denen Sie beitreten, indem Sie Folgendes tun:
df1.join(df2,['a'])
Dies funktioniert, wenn der Schlüssel, dem Sie beitreten, in beiden Tabellen identisch ist.
Siehe https://kb.databricks.com/data/join-two-dataframes-duplicated-columns.html
quelle
Mit der
def drop(col: Column)
Methode können Sie die duplizierte Spalte löschen, z. B.:DataFrame:df1 +-------+-----+ | a | f | +-------+-----+ |107831 | ... | |107831 | ... | +-------+-----+ DataFrame:df2 +-------+-----+ | a | f | +-------+-----+ |107831 | ... | |107831 | ... | +-------+-----+
Wenn ich df1 mit df2 verbinde, sieht der DataFrame wie folgt aus:
val newDf = df1.join(df2,df1("a")===df2("a")) DataFrame:newDf +-------+-----+-------+-----+ | a | f | a | f | +-------+-----+-------+-----+ |107831 | ... |107831 | ... | |107831 | ... |107831 | ... | +-------+-----+-------+-----+
Jetzt können wir die
def drop(col: Column)
Methode verwenden, um die duplizierte Spalte 'a' oder 'f' wie folgt zu löschen:val newDfWithoutDuplicate = df1.join(df2,df1("a")===df2("a")).drop(df2("a")).drop(df2("f"))
quelle
Nachdem ich mich in die Spark-API
alias
eingegraben hatte, stellte ich fest, dass ich zuerst einen Alias für den ursprünglichen Datenrahmen erstellen und dannwithColumnRenamed
jede Spalte des Alias manuell umbenennen kann. Dies führt dazu,join
dass der Spaltenname nicht dupliziert wird.Weitere Informationen finden Sie unter der Spark Dataframe-API :
pyspark.sql.DataFrame.alias
pyspark.sql.DataFrame.withColumnRenamed
Ich denke jedoch, dass dies nur eine mühsame Problemumgehung ist und frage mich, ob es einen besseren Weg für meine Frage gibt.
quelle
Auf diese Weise können wir in PySpark zwei Dataframes mit denselben Spaltennamen verbinden.
df = df1.join(df2, ['col1','col2','col3'])
Wenn Sie dies
printSchema()
danach tun , können Sie sehen, dass doppelte Spalten entfernt wurden.quelle
Angenommen, die DataFrames, denen Sie beitreten möchten, sind df1 und df2, und Sie verbinden sie in Spalte 'a'. Dann haben Sie zwei Methoden
Methode 1
Dies ist eine großartige Methode und wird dringend empfohlen.
Methode 2
quelle
def rename_duplicate_columns(dataframe): columns = dataframe.columns duplicate_column_indices = list(set([columns.index(col) for col in columns if columns.count(col) == 2])) for index in duplicate_column_indices: columns[index] = columns[index]+'2' dataframe = dataframe.toDF(*columns) return dataframe
quelle
Wenn nur die Schlüsselspalte in beiden Tabellen identisch ist, versuchen Sie es auf folgende Weise (Ansatz 1):
left. join(right , 'key', 'inner')
eher als unten (Ansatz 2):
left. join(right , left.key == right.key, 'inner')
Vorteile der Verwendung von Ansatz 1:
Nachteile der Verwendung von Ansatz 1:
quelle
Wenn Sie einen komplizierteren Anwendungsfall haben als in der Antwort von Glennie Helles Sindholt beschrieben, z. B. haben Sie andere / wenige nicht verknüpfte Spaltennamen, die ebenfalls identisch sind und diese bei der Auswahl unterscheiden möchten. Verwenden Sie am besten Aliasse, z.
df3 = df1.select("a", "b").alias("left")\ .join(df2.select("a", "b").alias("right"), ["a"])\ .select("left.a", "left.b", "right.b") df3.columns ['a', 'b', 'b']
quelle