Cómo eliminar columnas en pyspark dataframe


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]

Hay dos id: biginty quiero eliminar uno. ¿Como lo puedo hacer?

Respuestas:


118

Al leer la documentación de Spark, encontré una solución más sencilla.

Desde la versión 1.4 de Spark hay una función drop(col)que se puede usar en pyspark en un marco de datos.

Puedes usarlo de dos formas

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

Documentación de Pyspark - Drop


25
cuando el tamaño de los datos es grande, collect () puede provocar un error de espacio en la pila. También puede crear una nueva trama de datos dejando caer el campo extra porndf = df.drop('age')
mnis.p

1
Esta realmente debería ser la primera respuesta
vishalv2050

90

Agregando a la respuesta de @ Patrick, puede usar lo siguiente para eliminar varias columnas

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

4
Tuve que reasignar los resultados de la caída de nuevo al marco de datos: df = df.drop (* columnas_to_drop)
avgbody

1
Tenga en cuenta que no obtendrá un error si la columna no existe
Guido

Recibo un error que dice TreeNodeException: Binding attribute, tree: _gen_alias_34#34después de colocar una columna y usar.show()
frlzjosh

27

Una manera fácil de hacer esto es el usuario " select" y darse cuenta de que puede obtener una lista de todos columnspara el dataframe, dfcondf.columns

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

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

1
Gracias, esto funciona muy bien para mí para eliminar columnas duplicadas con el mismo nombre que otra columna, donde yo uso df.select([df.columns[column_num] for column_num in range(len(df.columns)) if column_num!=2]), donde la columna que quiero eliminar tiene el índice 2.
Shane Halloran

12

Puede nombrar explícitamente las columnas que desea mantener, así:

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

O en un enfoque más general, incluiría todas las columnas excepto una específica a través de una lista de comprensión. Por ejemplo, así (excluyendo la idcolumna de b):

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

Finalmente, realiza una selección en el resultado de su unión:

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

Creo que tengo la respuesta. Select necesita tomar una lista de cadenas, NO una lista de columnas. Entonces haz esto: 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

Bueno, eso debería hacer exactamente lo mismo que mi respuesta, ya que estoy bastante seguro de que selectacepta cadenas O columnas ( spark.apache.org/docs/latest/api/python/… ). Por cierto, en su línea keep = ...no hay necesidad de usar una lista de comprensión para a: a.columns + [c for c in b.columns if c != 'id']debería lograr exactamente lo mismo, como a.columnsya es una listde cadenas.
karlson

@ deusxmach1na En realidad, la selección de columnas basada en cadenas no puede funcionar para el OP, porque eso no resolvería la ambigüedad de la idcolumna. En ese caso, debe usar las Columninstancias en select.
karlson

Todos los buenos puntos. Probé su solución en Spark 1.3 y obtuve errores, así que lo que publiqué realmente funcionó para mí. Y para resolver la ambigüedad de la identificación, cambié el nombre de mi columna de identificación antes de la combinación y luego la eliminé después de la combinación usando la lista de conservación. HTH cualquier otra persona que estaba atascada como yo.
deusxmach1na

12

Puede utilizar de dos formas:

1: Solo mantén las columnas necesarias:

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

2: Esta es la forma más elegante.

df = df.drop("col_name")

Debe evitar la versión collect (), ya que enviará al maestro el conjunto de datos completo, ¡requerirá un gran esfuerzo informático!


3

Quizás un poco fuera de tema, pero aquí está la solución usando Scala. Cree un nombre Arrayde columna de su oldDataFramey elimine las columnas que desea eliminar ("colExclude"). A continuación, pasar la Array[Column]a selecty descomprimirlo.

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

-1

Considere 2 marcos de datos:

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

y

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

Para lograr lo que está buscando, hay 2 formas:

1. Condición de unión diferente. En lugar de decir aDF.id == bDF.id

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

Escribe esto:

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

Esto eliminará automáticamente el exceso del proceso de caída.

2. Use Aliasing: perderá datos relacionados con los ID específicos de B en esto.

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

Puede eliminar una columna como esta:

df.drop("column Name).columns

En tu caso :

df.drop("id").columns

Si desea eliminar más de una columna, puede hacer lo siguiente:

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

1
Spark 2.4 (y menos versiones) no acepta más de un nombre de columna.
seufagner

¿Es posible eliminar columnas por índice?
Horbaje

@seufagner, simplemente lo pasa como una lista
Dee
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.