Apache spark 如何删除pyspark dataframe中的列

Apache spark 如何删除pyspark dataframe中的列,apache-spark,apache-spark-sql,pyspark,Apache Spark,Apache Spark Sql,Pyspark,有两个id:bigint,我想删除一个。我该怎么做?您可以显式命名要保留的列,如下所示: >>> 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.i

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

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

>>> 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]
或者在更一般的方法中,您可以通过列表包含除特定列之外的所有列。例如这样(不包括
b
中的
id
列):

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

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

也许有点离题,但下面是使用Scala的解决方案。从您的
旧数据框中创建列名称的
数组
,并删除要删除的列
(“colExclude”)
。然后将
数组[列]
传递到
选择
并将其解压缩

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

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

自spark版本1.4以来,有一个函数
drop(col)
,可用于pyspark中的数据帧

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

  • df.drop('age').collect()
  • df.drop(df.age.collect()

  • 一个简单的方法是用户“
    选择
    ”,并意识到您可以为
    数据帧
    df
    ,以及
    df.columns

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

    除了@Patrick的答案,您可以使用以下命令删除多个列

    drop_list = ['a column', 'another column', ...]
    
    df.select([column for column in df.columns if column not in drop_list])
    
    您可以使用两种方式:

    1: 您只需保留必要的列:

    columns_to_drop = ['id', 'id_copy']
    df = df.drop(*columns_to_drop)
    
    2:这是比较优雅的方式

    drop_column_list = ["drop_column"]
    df = df.select([column for column in df.columns if column not in drop_column_list])  
    
    您应该避免使用collect()版本,因为它将向主机发送完整的数据集,这将需要大量的计算工作

    考虑两个数据帧:

    df = df.drop("col_name")
    

    要实现您的目标,有两种方法:

    1。不同的连接条件。而不是说aDF.id==bDF.id

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

    aDF.join(bDF, aDF.id == bDF.id, "outer")
    
    这将自动消除掉掉掉料过程中的多余部分

    2。使用别名:在此过程中,您将丢失与B特定Id相关的数据

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

    您可以这样删除列:

    >>> 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|
    +----+----+----+
    
    就你而言:

    df.drop("column Name).columns
    
    如果要删除多个列,可以执行以下操作:

    df.drop("id").columns
    

    是的,可以通过如下方式进行切片来拖放/选择列:

    >>> 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|
    +----+----+----+
    
    切片=数据。列[a:b]

    data.select(slice.show())

    例如:

    dfWithLongColName.drop("ORIGIN_COUNTRY_NAME", "DEST_COUNTRY_NAME")
    
    使用“选择”方法获取“要素”列:

    newDF = spark.createDataFrame([
                               (1, "a", "4", 0), 
                                (2, "b", "10", 3), 
                                (7, "b", "4", 1), 
                                (7, "d", "4", 9)],
                                ("id", "x1", "x2", "y"))
    
    
    slice = newDF.columns[1:3]
    newDF.select(slice).show()
    
    使用drop方法获取最后一列:

    features = newDF.columns[:-1]
    newDF.select(features).show()
    

    我想我知道答案了。Select需要获取字符串列表,而不是列列表。所以这样做:
    keep=[c代表a.columns中的c]+[c代表b.columns如果c!='id']
    d=a.join(b,a.id==b.id,'outer')。选择(*keep)
    这应该和我的答案完全一样,因为我非常确定
    select
    接受字符串或列()。顺便说一句,在你的行中,
    keep=…
    没有必要对
    a
    使用列表理解:
    a.columns+[c代表b.columns中的c.columns如果c!=“id”]
    应该达到完全相同的效果,因为
    a.columns
    已经是字符串的
    列表。@deusxmach1na实际上基于字符串的列选择不能用于OP,因为这不能解决
    id
    列的歧义性。在这种情况下,您必须使用
    选择中的
    实例。所有优点。我在Spark 1.3中尝试了您的解决方案,但出现了错误,所以我发布的内容实际上对我有用。为了解决id不明确的问题,我在连接之前重命名了id列,然后在连接之后使用keep列表将其删除。HTH任何其他像我一样被卡住的人。谢谢,这对于我删除与另一列同名的重复列非常有用,我在其中使用
    df.select([df.columns[column\u num]用于范围内的列(len(df.columns)),如果column\u num!=2])
    ,其中我要删除的列具有索引2。当数据大小较大时,collect()可能导致堆空间错误。您还可以通过
    ndf=df.drop('age')创建一个新的数据框来删除额外字段。
    我必须将删除结果重新分配回数据框:df=df.drop(*columns\u to\u drop)注意,如果该列不存在,您不会得到错误。我会得到一个错误,说
    TreeNodeException:Binding attribute,树:_gen_alias_34#34
    在我删除一列后,使用
    .show()
    星号
    *
    *列中的意思是什么
    *
    解压列表
    (*[a,b,c])
    变成
    (a,b,c)
    Spark 2.4(以及最低版本)不接受多个列名。是否可以按索引删除列?@seufagner它只是作为列表传递
    features = newDF.columns[:-1]
    newDF.select(features).show()
    
    last_col= newDF.drop(*features)
    last_col.show()