如何删除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]

有两个id: bigint,我想删除一个。我能怎么做?

Answers:


118

阅读Spark文档后,我发现了一个更简单的解决方案。

从spark的1.4版本开始,有一个函数drop(col)可以在数据帧上的pyspark中使用。

您可以通过两种方式使用它

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

Pyspark文档-删除


24
当数据大时,collect()可能会导致堆空间错误。您还可以创建一个新的数据ndf = df.drop('age')
框,

1
这确实应该是第一个答案
vishalv2050 '19

89

除了@Patrick的答案外,您还可以使用以下内容删除多列

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

4
我必须将删除结果重新分配回数据帧:df = df.drop(* columns_to_drop)
avgbody

1
请注意,如果列不存在,你不会得到一个错误
圭多

TreeNodeException: Binding attribute, tree: _gen_alias_34#34在删除列并使用后,我得到一个错误提示:.show()
frlzjosh

27

一个简单的方法做,这是对用户“ select”,并意识到你可以得到所有的列表columnsdataframedfdf.columns

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

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

1
感谢你,这对我的伟大工程具有相同的名称作为另一列,在这里我使用删除重复列df.select([df.columns[column_num] for column_num in range(len(df.columns)) if column_num!=2]),其中列我想删除具有索引2
巴蒂尔哈洛伦

12

您可以明确命名要保留的列,如下所示:

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

或者,以更一般的方法,您可以通过列表理解功能将除特定列之外的所有列都包括在内。例如这样的示例(不包括id来自的列b):

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

最后,对联接结果进行选择:

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

我想我得到了答案。Select需要采用字符串列表而不是列列表。这样做: 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 2015年

好吧,这应该和我的回答完全一样,因为我很确定可以select接受字符串或列(spark.apache.org/docs/latest/api/python/…)。顺便说一句,在您的行中keep = ...,无需对以下内容使用列表推导aa.columns + [c for c in b.columns if c != 'id']应该可以实现完全相同的功能,就像a.columns已经是list字符串一样。
karlson

@ deusxmach1na实际上,基于字符串的列选择不适用于OP,因为这不能解决id列的歧义。在这种情况下,您必须使用中的Column实例select
karlson

所有的优点。我在Spark 1.3中尝试了您的解决方案并出现错误,所以我发布的内容实际上对我有用。为了解决id的歧义性,我在连接之前重命名了id列,然后在连接之后使用keep列表将其删除。还有其他像我一样被困住的人。
deusxmach1na 2015年

12

您可以使用两种方式:

1:您只保留必要的列:

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

2:这是更优雅的方式。

df = df.drop("col_name")

您应该避免使用collect()版本,因为它将完整的数据集发送到主数据库,这将需要大量的计算工作!


3

也许有点偏离主题,但这是使用Scala的解决方案。Array从中创建一个列名称,oldDataFrame然后删除要删除的列("colExclude")。然后将传送Array[Column]select并解压。

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

-1

考虑2个dataFrames:

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

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

要完成您要寻找的东西,有两种方法:

1.不同的加入条件。而不是说aDF.id == bDF.id

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

这样写:

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

这将自动消除多余的删除过程。

2.使用别名:您将丢失与此B特定ID相关的数据。

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

您可以像这样删除列:

df.drop("column Name).columns

在您的情况下:

df.drop("id").columns

如果要删除多个列,可以执行以下操作:

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

1
Spark 2.4(以及最低版本)不接受多个列名。
seufagner

是否可以按索引删除列?
Horbaje

@seufagner它只是将其作为列表传递
Dee
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.