Cách xóa các cột trong khung dữ liệu pyspark


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]

Có hai id: bigintvà tôi muốn xóa một. Làm thế nào tôi có thể làm được?

Câu trả lời:


118

Đọc tài liệu Spark, tôi tìm thấy một giải pháp dễ dàng hơn.

Kể từ phiên bản 1.4 của spark có một hàm drop(col)có thể được sử dụng trong pyspark trên khung dữ liệu.

Bạn có thể sử dụng nó theo hai cách

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

Tài liệu Pyspark - Drop


24
khi kích thước dữ liệu lớn, collect () có thể gây ra lỗi vùng nhớ đống. bạn cũng có thể tạo ra một dataframe mới thả các trường bổ sung bởindf = df.drop('age')
mnis.p

1
Đây thực sự sẽ là câu trả lời đầu tiên
vishalv2050

89

Thêm vào câu trả lời của @ Patrick, bạn có thể sử dụng cách sau để thả nhiều cột

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

4
Tôi đã phải chỉ định lại kết quả thả trở lại khung dữ liệu: df = df.drop (* cột_to_drop)
avgbody

1
Lưu ý rằng bạn sẽ không gặp lỗi nếu cột không tồn tại
Guido

Tôi gặp lỗi thông báo TreeNodeException: Binding attribute, tree: _gen_alias_34#34sau khi tôi thả một cột và sử dụng.show()
frlzjosh

27

Một cách dễ dàng để làm điều này là sử dụng " select" và nhận ra bạn có thể nhận được một danh sách tất cả columnscho dataframe, dfvớidf.columns

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

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

1
Cảm ơn-bạn, điều này hoạt động tuyệt vời đối với tôi để loại bỏ cột trùng lặp với tên giống như cột khác, nơi mà tôi sử dụng df.select([df.columns[column_num] for column_num in range(len(df.columns)) if column_num!=2]), nơi cột tôi muốn loại bỏ có chỉ số 2.
Shane Halloran

12

Bạn có thể đặt tên rõ ràng cho các cột bạn muốn giữ lại, như sau:

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

Hoặc trong một cách tiếp cận tổng quát hơn, bạn sẽ bao gồm tất cả các cột ngoại trừ một cột cụ thể thông qua việc hiểu danh sách. Ví dụ như thế này (không bao gồm idcột từ b):

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

Cuối cùng, bạn lựa chọn kết quả tham gia của mình:

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

Tôi nghĩ rằng tôi đã có câu trả lời. Chọn cần lấy một danh sách các chuỗi KHÔNG phải một danh sách các cột. Vì vậy, hãy làm điều này: 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

Chà, điều đó sẽ thực hiện giống hệt như câu trả lời của tôi, vì tôi khá chắc chắn rằng nó selectchấp nhận một trong hai chuỗi HOẶC cột ( spark.apache.org/docs/latest/api/python/… ). Btw, trong dòng của bạn keep = ..., không cần phải sử dụng khả năng hiểu danh sách cho a: a.columns + [c for c in b.columns if c != 'id']nên đạt được điều tương tự chính xác, như a.columnsđã là một listchuỗi.
karlson

@ deusxmach1na Trên thực tế, việc chọn cột dựa trên chuỗi không thể hoạt động đối với OP, vì điều đó sẽ không giải quyết được sự mơ hồ của idcột. Trong trường hợp đó, bạn phải sử dụng các Columnphiên bản trong select.
karlson

Tất cả các điểm tốt. Tôi đã thử giải pháp của bạn trong Spark 1.3 và gặp lỗi, vì vậy những gì tôi đã đăng thực sự hiệu quả với tôi. Và để giải quyết sự không rõ ràng về id, tôi đã đổi tên cột id của mình trước khi tham gia rồi bỏ nó sau khi tham gia bằng cách sử dụng danh sách giữ. HTH bất cứ ai khác mà đã bị mắc kẹt như tôi.
deusxmach1na

12

Bạn có thể sử dụng hai cách:

1: Bạn chỉ cần giữ lại các cột cần thiết:

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

2: Đây là cách thanh lịch hơn.

df = df.drop("col_name")

Bạn nên tránh phiên bản Collect (), vì nó sẽ gửi cho người chủ toàn bộ tập dữ liệu, sẽ tốn một công sức tính toán lớn!


3

Có thể hơi lạc đề, nhưng đây là giải pháp sử dụng Scala. Tạo Arraytên cột từ của bạn oldDataFramevà xóa các cột bạn muốn bỏ ("colExclude"). Sau đó chuyển Array[Column]đến selectvà giải nén nó.

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

-1

Hãy xem xét 2 dữ liệu

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

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

Để đạt được những gì bạn đang tìm kiếm, có 2 cách:

1. Điều kiện gia nhập khác nhau. Thay vì nói aDF.id == bDF.id

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

Ghi chép lại cái đó:

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

Điều này sẽ tự động loại bỏ quá trình giảm thêm.

2. Sử dụng Bí danh: Bạn sẽ mất dữ liệu liên quan đến B Cụ thể của Id trong này.

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

Bạn có thể xóa cột như thế này:

df.drop("column Name).columns

Trong trường hợp của bạn :

df.drop("id").columns

Nếu bạn muốn bỏ nhiều hơn một cột, bạn có thể làm:

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

1
Spark 2.4 (và ít phiên bản nhất) không chấp nhận nhiều hơn một tên cột.
seufagner

Có thể giảm các cột theo chỉ mục?
Horbaje

@seufagner nó chỉ chuyển nó như một danh sách
Dee
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.