Eliminación de varias columnas en función de los nombres de las columnas

5 minutos de lectura

Avatar de usuario de Peadar Coyle
Peadar Coyle

Tengo algunos datos y cuando los importo, obtengo las siguientes columnas innecesarias. Estoy buscando una manera fácil de eliminar todos estos.

'Unnamed: 24', 'Unnamed: 25', 'Unnamed: 26', 'Unnamed: 27',
'Unnamed: 28', 'Unnamed: 29', 'Unnamed: 30', 'Unnamed: 31',
'Unnamed: 32', 'Unnamed: 33', 'Unnamed: 34', 'Unnamed: 35',
'Unnamed: 36', 'Unnamed: 37', 'Unnamed: 38', 'Unnamed: 39',
'Unnamed: 40', 'Unnamed: 41', 'Unnamed: 42', 'Unnamed: 43',
'Unnamed: 44', 'Unnamed: 45', 'Unnamed: 46', 'Unnamed: 47',
'Unnamed: 48', 'Unnamed: 49', 'Unnamed: 50', 'Unnamed: 51',
'Unnamed: 52', 'Unnamed: 53', 'Unnamed: 54', 'Unnamed: 55',
'Unnamed: 56', 'Unnamed: 57', 'Unnamed: 58', 'Unnamed: 59',
'Unnamed: 60'

Están indexados por indexación 0, así que probé algo como

df.drop(df.columns[[22, 23, 24, 25, 
26, 27, 28, 29, 30, 31, 32 ,55]], axis=1, inplace=True)

Pero esto no es muy eficiente. Traté de escribir algunos bucles for pero esto me pareció un mal comportamiento de Pandas. Por lo tanto, hago la pregunta aquí.

He visto algunos ejemplos que son similares (eliminar varias columnas en pandas), pero esto no responde a mi pregunta.

  • ¿A qué te refieres con eficiente? ¿Está funcionando demasiado lento? Si su problema es que no desea obtener los índices de todas las columnas que desea eliminar, tenga en cuenta que solo puede dar df.drop una lista de nombres de columna: df.drop(['Unnamed: 24', 'Unnamed: 25', ...], axis=1)

    – Carsten

    16 de febrero de 2015 a las 9:53

  • ¿No sería más fácil subdividir las columnas de interés: es decir, df = df[cols_of_interest]de lo contrario, podría dividir el df por columnas y obtener las columnas df.drop(df.ix[:,'Unnamed: 24':'Unnamed: 60'].head(0).columns, axis=1)

    – EdChum

    16 de febrero de 2015 a las 9:56

  • Quise decir ineficiente en términos de tipeo o ‘mal olor a código’

    –Peadar Coyle

    17 de febrero de 2015 a las 11:03

  • Vale la pena señalar que, en la mayoría de los casos, es más fácil mantener las columnas que desea y luego eliminar las que no: df = df[‘col_list’]

    – gorrión

    27 de abril de 2018 a las 22:14

Avatar de usuario de Philipp Schwarz
felipe schwarz

Con mucho, el enfoque más simple es:

yourdf.drop(['columnheading1', 'columnheading2'], axis=1, inplace=True)

  • Usé este formato en parte de mi código y obtengo un SettingWithCopyWarning ¿advertencia?

    – KillerSnail

    8 de enero de 2017 a las 15:42

  • @KillerSnail, es seguro ignorarlo. Para evitar errores, intente: df = df.drop([‘colheading1’, ‘colheading2’]eje=1)

    – Philipp Schwarz

    9 de enero de 2017 a las 13:55


  • El término axis explicado: stackoverflow.com/questions/22149584/…. Esencialmente, axis=0 se dice que es “en columna” y axis=1 es “en filas”.

    – Rohmer

    16 de junio de 2017 a las 18:07


  • Y inplace=True significa que el DataFrame se modifica en su lugar.

    – Rohmer

    16 de junio de 2017 a las 18:07


  • @Killernail si no quieres la advertencia, hazlo yourdf = yourdf.drop(['columnheading1', 'columnheading2'], axis=1)

    – feliz_sísyfo

    12/10/2017 a las 16:32

Avatar de usuario de EdChum
EdChum

No sé a qué te refieres con ineficiente, pero si te refieres a escribir, podría ser más fácil simplemente seleccionar las columnas de interés y asignarlas nuevamente al df:

df = df[cols_of_interest]

Dónde cols_of_interest es una lista de las columnas que le interesan.

O puede dividir las columnas y pasar esto a drop:

df.drop(df.ix[:,'Unnamed: 24':'Unnamed: 60'].head(0).columns, axis=1)

la llamada a head solo selecciona 0 filas ya que solo nos interesan los nombres de las columnas en lugar de los datos

actualizar

Otro método: sería más sencillo usar la máscara booleana de str.contains e invertirlo para enmascarar las columnas:

In [2]:
df = pd.DataFrame(columns=['a','Unnamed: 1', 'Unnamed: 1','foo'])
df

Out[2]:
Empty DataFrame
Columns: [a, Unnamed: 1, Unnamed: 1, foo]
Index: []

In [4]:
~df.columns.str.contains('Unnamed:')

Out[4]:
array([ True, False, False,  True], dtype=bool)

In [5]:
df[df.columns[~df.columns.str.contains('Unnamed:')]]

Out[5]:
Empty DataFrame
Columns: [a, foo]
Index: []

  • Recibo errores cuando intento hacer ~df.columns… (TypeError: tipo de operando incorrecto para unario ~: ‘str’) o df.columns.str.contains… (AttributeError: el objeto ‘Index’ no tiene atributo ‘str’). ¿Alguna idea de por qué esto podría ser?

    – Dai

    3 de junio de 2017 a las 8:37

  • @EdChum puedo crear df = df[cols_of_interest]dónde cols_of_interest ¿Agrega un nombre de columna cada vez que itera un bucle for?

    usuario9238790

    22 de febrero de 2018 a las 9:52


  • @Victor no, si haces eso, sobrescribes tu df con tu nueva columna deberías append tal vez, pero realmente no entiendo su pregunta, debería publicar una pregunta real en SO en lugar de preguntar como un comentario, ya que es una forma deficiente en SO

    – EdChum

    22 de febrero de 2018 a las 9:54

  • @EdChum tienes toda la razón. Creé la pregunta y estoy tratando de resolverla buscando en diferentes partes de SO. Aqui esta el link ! cualquier contribución ayudará stackoverflow.com/questions/48923915/…

    usuario9238790

    22 de febrero de 2018 a las 9:55

avatar de usuario de sheldonzy
sheldonzy

Mi favorito personal, y más fácil que las respuestas que he visto aquí (para varias columnas):

df.drop(df.columns[22:56], axis=1, inplace=True)

  • Esta debería ser la respuesta. Más limpio, más fácil de leer, con sintaxis de indexación de Pandas nativa directa.

    –Brent Fausto

    5 oct 2017 a las 21:44

  • Esta respuesta debe tener la marca verde junto a ella, no las demás.

    – Siavosh Mahbubian

    20 de agosto de 2019 a las 23:41

Esta es probablemente una buena manera de hacer lo que quieres. Eliminará todas las columnas que contengan ‘Sin nombre’ en su encabezado.

for col in df.columns:
    if 'Unnamed' in col:
        del df[col]

Puedes hacer esto en una línea y de una sola vez:

df.drop([col for col in df.columns if "Unnamed" in col], axis=1, inplace=True)

Esto implica menos movimiento/copia del objeto que las soluciones anteriores.

avatar de usuario de px06
px06

No estoy seguro de si esta solución se ha mencionado en alguna parte todavía, pero una forma de hacerlo es pandas.Index.difference.

>>> df = pd.DataFrame(columns=['A','B','C','D'])
>>> df
Empty DataFrame
Columns: [A, B, C, D]
Index: []
>>> to_remove = ['A','C']
>>> df = df[df.columns.difference(to_remove)]
>>> df
Empty DataFrame
Columns: [B, D]
Index: []

Avatar de usuario de Swaroop Maddu
Swaroop Maddu

Simplemente puede pasar los nombres de las columnas como una lista especificando el eje como 0 o 1

  • axis=1: a lo largo de las filas
  • axis=0: A lo largo de las Columnas
  • Por defecto eje=0

    data.drop(["Colname1","Colname2","Colname3","Colname4"],axis=1)

¿Ha sido útil esta solución?