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?

xjx0524
fuente

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

Patrick C.
fuente
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)
Reloj esclavo
fuente
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])
ev.per.baryon
fuente
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)
karlson
fuente
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!

Aron Asztalos
fuente
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: _*)
Yuri Brovman
fuente
-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|
+----+----+----+
Nuevo codificador
fuente
-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")
techgeek
fuente
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