Jak usunąć kolumny w ramce danych pyspark


82
>>> 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]

Są dwa id: biginti chcę usunąć jeden. Jak mam to zrobić?

Odpowiedzi:


122

Czytając dokumentację Sparka znalazłem łatwiejsze rozwiązanie.

Od wersji 1.4 Spark istnieje funkcja, drop(col)której można użyć w pysparku na ramce danych.

Możesz go używać na dwa sposoby

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

Dokumentacja Pyspark - Drop


26
gdy rozmiar danych jest duży, metoda collect () może powodować błąd miejsca na sterty. możesz również utworzyć nową ramkę danych, upuszczając dodatkowe pole przezndf = df.drop('age')
mnis.p

1
To naprawdę powinna być pierwsza odpowiedź
vishalv2050

97

Dodając do odpowiedzi @ Patricka, możesz użyć poniższego, aby upuścić wiele kolumn

columns_to_drop = ['id', 'id_copy']
df = df.drop(*columns_to_drop)

4
Musiałem ponownie przypisać wyniki upuszczania z powrotem do ramki danych: df = df.drop (* columns_to_drop)
avgbody

1
Zauważ, że nie otrzymasz błędu, jeśli kolumna nie istnieje
Guido

TreeNodeException: Binding attribute, tree: _gen_alias_34#34Po upuszczeniu kolumny pojawia się błąd i używam.show()
frlzjosh

28

Łatwym sposobem, aby to zrobić, to użytkownik „ select” i uświadomić sobie, można uzyskać listę wszystkich columnsdla dataframe, dfzdf.columns

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

df.select([column for column in df.columns if column not in drop_list])

1
Dziękuję-ty, to działa świetnie dla mnie do usuwania zduplikowanych kolumny o tej samej nazwie, jak nazwa innej kolumnie, w której używam df.select([df.columns[column_num] for column_num in range(len(df.columns)) if column_num!=2]), gdzie kolumna Chcę usunąć posiada indeks 2.
Shane Halloran

12

Możesz jawnie nazwać kolumny, które chcesz zachować, na przykład:

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

Lub w bardziej ogólnym podejściu uwzględnisz wszystkie kolumny z wyjątkiem konkretnej za pomocą rozumienia listy. Na przykład w ten sposób (z wyłączeniem idkolumny z b):

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

Na koniec dokonujesz wyboru wyniku dołączenia:

d = a.join(b, a.id==b.id, 'outer').select(*keep)

Myślę, że mam odpowiedź. Wybierz, aby pobrać listę ciągów, a nie listę kolumn. Więc zrób to: 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

Cóż, powinno to zrobić dokładnie to samo, co moja odpowiedź, ponieważ jestem prawie pewien, że selectakceptuje ciągi znaków LUB kolumny ( spark.apache.org/docs/latest/api/python/ ... ). Przy okazji, w twoim wierszu keep = ...nie ma potrzeby używania wyrażenia listowego dla a: a.columns + [c for c in b.columns if c != 'id']powinno osiągnąć dokładnie to samo, co a.columnsjuż jest listze stringów.
karlson

@ deusxmach1na W rzeczywistości wybór kolumny oparty na łańcuchach nie może działać dla OP, ponieważ nie rozwiązałoby to niejednoznaczności idkolumny. W takim przypadku musisz użyć Columninstancji w select.
karlson

Wszystkie dobre strony. Wypróbowałem Twoje rozwiązanie w Spark 1.3 i otrzymałem błędy, więc to, co opublikowałem, faktycznie zadziałało. Aby rozwiązać niejednoznaczność id, zmieniłem nazwę mojej kolumny id przed złączeniem, a następnie porzuciłem ją po złączeniu, używając listy zachowania. HTH kogokolwiek innego, kto utknął tak jak ja.
deusxmach1na

12

Możesz użyć dwóch sposobów:

1: Po prostu zachowaj niezbędne kolumny:

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

2: To jest bardziej elegancki sposób.

df = df.drop("col_name")

Powinieneś unikać wersji collect (), ponieważ wyśle ​​ona do mastera kompletny zestaw danych, będzie to wymagało dużego wysiłku obliczeniowego!


3

Może trochę poza tematem, ale oto rozwiązanie wykorzystujące Scala. Utwórz Arrayz nazw kolumn ze swojego oldDataFramei usuń kolumny, które chcesz usunąć ("colExclude"). Następnie przekaż Array[Column]go selecti rozpakuj.

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

-1

Rozważ 2 ramki dataFrames:

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

i

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

Aby osiągnąć to, czego szukasz, istnieją 2 sposoby:

1. Różne warunki łączenia. Zamiast mówić aDF.id == bDF.id

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

Napisz to:

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

To automatycznie pozbędzie się dodatkowego procesu upuszczania.

2. Użyj aliasingu: w tym przypadku utracisz dane związane z określonymi identyfikatorami B.

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

-2

Możesz usunąć kolumnę w ten sposób:

df.drop("column Name).columns

W Twoim przypadku :

df.drop("id").columns

Jeśli chcesz upuścić więcej niż jedną kolumnę, możesz zrobić:

dfWithLongColName.drop("ORIGIN_COUNTRY_NAME", "DEST_COUNTRY_NAME")

1
Spark 2.4 (i najmniej wersje) nie akceptuje więcej niż jednej nazwy kolumny.
seufagner

Czy można upuszczać kolumny według indeksu?
Horbaje

@seufagner po prostu przekazuje to jako listę
Dee,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.