So löschen Sie Spalten im pyspark-Datenrahmen

81
>>> a
DataFrame[id: bigint, julian_date: string, user_id: bigint]
>>> b
DataFrame[id: bigint, quan_created_money: decimal(10,0), quan_created_cnt: bigint]
>>> a.join(b, a.id==b.id, 'outer')
DataFrame[id: bigint, julian_date: string, user_id: bigint, id: bigint, quan_created_money: decimal(10,0), quan_created_cnt: bigint]

Es gibt zwei id: bigintund ich möchte einen löschen. Wie kann ich?

xjx0524
quelle

Antworten:

118

Beim Lesen der Spark-Dokumentation fand ich eine einfachere Lösung.

Seit Version 1.4 von spark gibt es eine Funktion drop(col), die in pyspark auf einem Datenrahmen verwendet werden kann.

Sie können es auf zwei Arten verwenden

  1. df.drop('age').collect()
  2. df.drop(df.age).collect()

Pyspark-Dokumentation - Drop

Patrick C.
quelle
24
Wenn die Datengröße groß ist, kann collect () einen Heap-Space-Fehler verursachen. Sie können auch einen neuen Datenrahmen erstellen, der das zusätzliche Feld durchndf = df.drop('age')
mnis.p
1
Dies sollte wirklich die erste Antwort sein
vishalv2050
89

Wenn Sie die Antwort von @ Patrick hinzufügen, können Sie Folgendes verwenden, um mehrere Spalten zu löschen

columns_to_drop = ['id', 'id_copy']
df = df.drop(*columns_to_drop)
Uhrensklave
quelle
4
Ich musste die Drop-Ergebnisse wieder dem Datenrahmen zuweisen: df = df.drop (* column_to_drop)
avgbody
1
Beachten Sie, dass Sie keine Fehlermeldung erhalten, wenn die Spalte nicht vorhanden ist
Guido
Ich erhalte eine Fehlermeldung, TreeNodeException: Binding attribute, tree: _gen_alias_34#34nachdem ich eine Spalte .show()
gelöscht
27

Eine einfache Möglichkeit , dies zu tun ist , um Benutzer „ select“ und erkennen Sie eine Liste aller bekommen columnsfür das dataframe, dfmitdf.columns

drop_list = ['a column', 'another column', ...]

df.select([column for column in df.columns if column not in drop_list])
ev.per.baryon
quelle
1
Vielen Dank, dies funktioniert hervorragend für mich, um doppelte Spalten mit demselben Namen wie eine andere Spalte df.select([df.columns[column_num] for column_num in range(len(df.columns)) if column_num!=2])zu entfernen, in der die Spalte, die ich entfernen möchte, den Index 2 hat.
Shane Halloran
12

Sie können die Spalten, die Sie behalten möchten, entweder explizit benennen, wie folgt:

keep = [a.id, a.julian_date, a.user_id, b.quan_created_money, b.quan_created_cnt]

Oder in einem allgemeineren Ansatz würden Sie alle Spalten außer einer bestimmten über ein Listenverständnis einschließen. Zum Beispiel so (ohne die idSpalte von b):

keep = [a[c] for c in a.columns] + [b[c] for c in b.columns if c != 'id']

Schließlich treffen Sie eine Auswahl für Ihr Join-Ergebnis:

d = a.join(b, a.id==b.id, 'outer').select(*keep)
Karlson
quelle
Ich glaube ich habe die Antwort bekommen. Select muss eine Liste von Zeichenfolgen enthalten, NICHT eine Liste von Spalten. Also mach das: keep = [c for c in a.columns] + [c for c in b.columns if c != 'id'] d = a.join(b, a.id==b.id, 'outer').select(*keep)
deusxmach1na
Nun, das sollte genau das Gleiche tun wie meine Antwort, da ich mir ziemlich sicher bin, dass selectentweder Zeichenfolgen ODER Spalten akzeptiert werden ( spark.apache.org/docs/latest/api/python/… ). Übrigens müssen Sie in Ihrer Zeile keep = ...kein Listenverständnis verwenden für a: a.columns + [c for c in b.columns if c != 'id']sollte genau das Gleiche erreichen, wie a.columnses bereits eine listvon Zeichenfolgen ist.
Karlson
@ deusxmach1na Tatsächlich kann die auf Zeichenfolgen basierende Spaltenauswahl für das OP nicht funktionieren, da dies die Mehrdeutigkeit der idSpalte nicht lösen würde . In diesem Fall müssen Sie die ColumnInstanzen in verwenden select.
Karlson
Alles gute Punkte. Ich habe Ihre Lösung in Spark 1.3 ausprobiert und Fehler erhalten. Das, was ich gepostet habe, hat also tatsächlich für mich funktioniert. Und um die ID-Mehrdeutigkeit zu beheben, habe ich meine ID-Spalte vor dem Join umbenannt und sie nach dem Join mithilfe der Keep-Liste gelöscht. HTH jemand anderes, der so feststeckte wie ich.
Deusxmach1na
12

Sie können zwei Möglichkeiten verwenden:

1: Sie behalten nur die erforderlichen Spalten:

drop_column_list = ["drop_column"]
df = df.select([column for column in df.columns if column not in drop_column_list])  

2: Dies ist der elegantere Weg.

df = df.drop("col_name")

Sie sollten die collect () -Version vermeiden, da sie den gesamten Datensatz an den Master sendet und einen hohen Rechenaufwand erfordert!

Aron Asztalos
quelle
3

Vielleicht ein bisschen abseits des Themas, aber hier ist die Lösung mit Scala. Erstellen Sie einen ArraySpaltennamen aus Ihrem oldDataFrameund löschen Sie die Spalten, die Sie löschen möchten ("colExclude"). Dann passieren die Array[Column]auf selectund entpacken Sie es.

val columnsToKeep: Array[Column] = oldDataFrame.columns.diff(Array("colExclude"))
                                               .map(x => oldDataFrame.col(x))
val newDataFrame: DataFrame = oldDataFrame.select(columnsToKeep: _*)
Yuri Brovman
quelle
-1

Betrachten Sie 2 dataFrames:

>>> aDF.show()
+---+----+
| id|datA|
+---+----+
|  1|  a1|
|  2|  a2|
|  3|  a3|
+---+----+

und

>>> bDF.show()
+---+----+
| id|datB|
+---+----+
|  2|  b2|
|  3|  b3|
|  4|  b4|
+---+----+

Um das zu erreichen, wonach Sie suchen, gibt es zwei Möglichkeiten:

1. Unterschiedliche Verbindungsbedingungen. Anstatt aDF.id == bDF.id zu sagen

aDF.join(bDF, aDF.id == bDF.id, "outer")

Schreib Dies:

aDF.join(bDF, "id", "outer").show()
+---+----+----+
| id|datA|datB|
+---+----+----+
|  1|  a1|null|
|  3|  a3|  b3|
|  2|  a2|  b2|
|  4|null|  b4|
+---+----+----+

Dadurch wird der zusätzliche Löschvorgang automatisch beseitigt.

2. Verwenden Sie Aliasing: Sie verlieren Daten in Bezug auf B-spezifische IDs.

>>> from pyspark.sql.functions import col
>>> aDF.alias("a").join(bDF.alias("b"), aDF.id == bDF.id, "outer").drop(col("b.id")).show()

+----+----+----+
|  id|datA|datB|
+----+----+----+
|   1|  a1|null|
|   3|  a3|  b3|
|   2|  a2|  b2|
|null|null|  b4|
+----+----+----+
Neuer Codierer
quelle
-2

Sie können eine Spalte wie folgt löschen:

df.drop("column Name).columns

In deinem Fall :

df.drop("id").columns

Wenn Sie mehr als eine Spalte löschen möchten, haben Sie folgende Möglichkeiten:

dfWithLongColName.drop("ORIGIN_COUNTRY_NAME", "DEST_COUNTRY_NAME")
Techgeek
quelle
1
Spark 2.4 (und die wenigsten Versionen) akzeptiert nicht mehr als einen Spaltennamen.
Seufagner
Ist es möglich, Spalten nach Index zu löschen?
Horbaje
@seufagner es wird nur als Liste übergeben
Dee