Tengo un marco de datos de pandas donde las columnas se nombran como:

0,1,2,3,4,.....,n

Me gustaría eliminar cada tercera columna para obtener un nuevo marco de datos donde tendría las columnas como:

0,1,3,4,6,7,9,.....,n

He intentado así:

shape = df.shape[1]
for i in range(2,shape,3):
    df = df.drop(df.columns[i], axis=1) 

Pero obtengo un error que dice que el índice está fuera de límites y supongo que esto sucede porque la forma del marco de datos cambia cuando dejo caer las columnas. si simplemente no almaceno la salida del bucle "for", entonces el código funciona pero no obtengo mi nuevo marco de datos.

¿Cómo puedo solucionar esto? Gracias

0
Samiur Rahman 9 dic. 2020 a las 15:27

3 respuestas

La mejor respuesta

El problema con el código es , cada vez que sueltas una columna en tu ciclo, terminas con un conjunto diferente de columnas porque sobrescribes la df de nuevo después de cada iteración. Cuando intentas eliminar la siguiente tercera columna de ESE nuevo conjunto de columnas, no solo eliminas la incorrecta, sino que finalmente terminas quedándote sin columnas. Es por eso que recibe el error que está obteniendo.

iter1 -> 0,1,3,4,5,6,7,8,9,10 ... n #first you drop 2 which is 3rd col
iter2 -> 0,1,3,4,5,7,8,9,10 ... n   #next you drop 6 which is 6th col (should be 5)
iter3 -> 0,1,3,4,5,7,8,9, ... n     #next you drop 10 which is 9th col (should be 8)

Lo que quiere hacer es calcular los índices de antemano y luego eliminarlos de una vez.


Simplemente puede obtener los índices de las columnas que desea eliminar con rango y luego eliminarlos.

drop_idx = list(range(2,df.shape[1],3)) #Indexes to drop
df2 = df.drop(drop_idx, axis=1)         #Drop them at once over axis=1


print('old columns->', list(df.columns))
print('idx to drop->', drop_idx)
print('new columns->',list(df2.columns))
old columns-> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
idx to drop-> [2, 5, 8]
new columns-> [0, 1, 3, 4, 6, 7, 9]
1
Akshay Sehgal 9 dic. 2020 a las 15:28

Aquí hay una solución con lógica invertida: seleccione todas las columnas con cada tercera columna eliminada.

Puede filtrar valores comparando 1 agregado a la matriz auxiliar, con 3 módulos de comparación para no iguales 0 y pasar a DataFrame.loc:

df = pd.DataFrame({
        'A':list('abcdef'),
         'B':[4,5,4,5,5,4],
         'C':[7,8,9,4,2,3],
         'D':[1,3,5,7,1,0],
         'E':[5,3,6,9,2,4],
         'F':list('aaabbb')
})

df = df.loc[:, (np.arange(len(df.columns)) + 1) % 3 != 0]
print (df)
   A  B  D  E
0  a  4  1  5
1  b  5  3  3
2  c  4  5  6
3  d  5  7  9
4  e  5  1  2
5  f  4  0  4
0
jezrael 9 dic. 2020 a las 12:53

Puede utilizar la comprensión de listas para filtrar columnas:

df = df[[k for k in df.columns if (k + 1) % 3 != 0]]

Si los nombres son diferentes (por ejemplo, cadenas) y desea descartar cada tercera columna independientemente de su nombre, entonces:

df = df[[k for i, k in enumerate(df.columns, 1) if i % 3 != 0]]
0
Pierre D 9 dic. 2020 a las 12:33
65216773