tutorial index from espaƱol empty data create python pandas dataframe

python - index - pandas dataframe tutorial



Elimine la columna de Pandas DataFrame usando del df.column_name (14)

Pandas 0.21+ respuesta

La versión 0.21 de Pandas ha cambiado el método de drop ligeramente para incluir los parámetros de index y columns para que coincida con la firma de los métodos de rename y reindex .

df.drop(columns=[''column_a'', ''column_c''])

Personalmente, prefiero usar el parámetro axis para denotar columnas o índice porque es el parámetro de palabra clave predominante utilizado en casi todos los métodos pandas. Pero, ahora tienes algunas opciones agregadas en la versión 0.21.

Cuando borro una columna en un DataFrame, uso:

del df[''column_name'']

Y esto funciona muy bien. ¿Por qué no puedo usar lo siguiente?

del df.column_name

Como puede acceder a la columna / Serie como df.column_name , espero que esto funcione.


TL; DR

Mucho esfuerzo para encontrar una solución marginalmente más eficiente. Es difícil justificar la complejidad agregada mientras se sacrifica la simplicidad de df.drop(dlst, 1, errors=''ignore'')

df.reindex_axis(np.setdiff1d(df.columns.values, dlst), 1)

Preámbulo
Eliminar una columna es semánticamente lo mismo que seleccionar las otras columnas. Mostraré algunos métodos adicionales para considerar.

También me centraré en la solución general de eliminar varias columnas a la vez y permitir el intento de eliminar columnas que no están presentes.

El uso de estas soluciones es general y también funcionará para el caso simple.

Preparar
Tenga en cuenta el df pd.DataFrame y la lista para eliminar dlst

df = pd.DataFrame(dict(zip(''ABCDEFGHIJ'', range(1, 11))), range(3)) dlst = list(''HIJKLM'')

df A B C D E F G H I J 0 1 2 3 4 5 6 7 8 9 10 1 1 2 3 4 5 6 7 8 9 10 2 1 2 3 4 5 6 7 8 9 10

dlst [''H'', ''I'', ''J'', ''K'', ''L'', ''M'']

El resultado debe verse como:

df.drop(dlst, 1, errors=''ignore'') A B C D E F G 0 1 2 3 4 5 6 7 1 1 2 3 4 5 6 7 2 1 2 3 4 5 6 7

Ya que estoy igualando la eliminación de una columna para seleccionar las otras columnas, la dividiré en dos tipos:

  1. Selección de etiquetas
  2. Selección booleana

Selección de etiquetas

Comenzamos fabricando la lista / matriz de etiquetas que representan las columnas que queremos mantener y sin las columnas que queremos eliminar.

  1. df.columns.difference(dlst)

    Index([''A'', ''B'', ''C'', ''D'', ''E'', ''F'', ''G''], dtype=''object'')

  2. np.setdiff1d(df.columns.values, dlst)

    array([''A'', ''B'', ''C'', ''D'', ''E'', ''F'', ''G''], dtype=object)

  3. df.columns.drop(dlst, errors=''ignore'')

    Index([''A'', ''B'', ''C'', ''D'', ''E'', ''F'', ''G''], dtype=''object'')

  4. list(set(df.columns.values.tolist()).difference(dlst))

    # does not preserve order [''E'', ''D'', ''B'', ''F'', ''G'', ''A'', ''C'']

  5. [x for x in df.columns.values.tolist() if x not in dlst]

    [''A'', ''B'', ''C'', ''D'', ''E'', ''F'', ''G'']

Columnas de etiquetas
Para poder comparar el proceso de selección, asuma:

cols = [x for x in df.columns.values.tolist() if x not in dlst]

Entonces podemos evaluar

  1. df.loc[:, cols]
  2. df[cols]
  3. df.reindex(columns=cols)
  4. df.reindex_axis(cols, 1)

Que todos evalúan a:

A B C D E F G 0 1 2 3 4 5 6 7 1 1 2 3 4 5 6 7 2 1 2 3 4 5 6 7

Rebanada booleana

Podemos construir una matriz / lista de booleanos para rebanar

  1. ~df.columns.isin(dlst)
  2. ~np.in1d(df.columns.values, dlst)
  3. [x not in dlst for x in df.columns.values.tolist()]
  4. (df.columns.values[:, None] != dlst).all(1)

Columnas de booleano
Por el bien de la comparación

bools = [x not in dlst for x in df.columns.values.tolist()]

  1. df.loc[: bools]

Que todos evalúan a:

A B C D E F G 0 1 2 3 4 5 6 7 1 1 2 3 4 5 6 7 2 1 2 3 4 5 6 7

Tiempo robusto

Funciones

setdiff1d = lambda df, dlst: np.setdiff1d(df.columns.values, dlst) difference = lambda df, dlst: df.columns.difference(dlst) columndrop = lambda df, dlst: df.columns.drop(dlst, errors=''ignore'') setdifflst = lambda df, dlst: list(set(df.columns.values.tolist()).difference(dlst)) comprehension = lambda df, dlst: [x for x in df.columns.values.tolist() if x not in dlst] loc = lambda df, cols: df.loc[:, cols] slc = lambda df, cols: df[cols] ridx = lambda df, cols: df.reindex(columns=cols) ridxa = lambda df, cols: df.reindex_axis(cols, 1) isin = lambda df, dlst: ~df.columns.isin(dlst) in1d = lambda df, dlst: ~np.in1d(df.columns.values, dlst) comp = lambda df, dlst: [x not in dlst for x in df.columns.values.tolist()] brod = lambda df, dlst: (df.columns.values[:, None] != dlst).all(1)

Pruebas

res1 = pd.DataFrame( index=pd.MultiIndex.from_product([ ''loc slc ridx ridxa''.split(), ''setdiff1d difference columndrop setdifflst comprehension''.split(), ], names=[''Select'', ''Label'']), columns=[10, 30, 100, 300, 1000], dtype=float ) res2 = pd.DataFrame( index=pd.MultiIndex.from_product([ ''loc''.split(), ''isin in1d comp brod''.split(), ], names=[''Select'', ''Label'']), columns=[10, 30, 100, 300, 1000], dtype=float ) res = res1.append(res2).sort_index() dres = pd.Series(index=res.columns, name=''drop'') for j in res.columns: dlst = list(range(j)) cols = list(range(j // 2, j + j // 2)) d = pd.DataFrame(1, range(10), cols) dres.at[j] = timeit(''d.drop(dlst, 1, errors="ignore")'', ''from __main__ import d, dlst'', number=100) for s, l in res.index: stmt = ''{}(d, {}(d, dlst))''.format(s, l) setp = ''from __main__ import d, dlst, {}, {}''.format(s, l) res.at[(s, l), j] = timeit(stmt, setp, number=100) rs = res / dres

rs 10 30 100 300 1000 Select Label loc brod 0.747373 0.861979 0.891144 1.284235 3.872157 columndrop 1.193983 1.292843 1.396841 1.484429 1.335733 comp 0.802036 0.732326 1.149397 3.473283 25.565922 comprehension 1.463503 1.568395 1.866441 4.421639 26.552276 difference 1.413010 1.460863 1.587594 1.568571 1.569735 in1d 0.818502 0.844374 0.994093 1.042360 1.076255 isin 1.008874 0.879706 1.021712 1.001119 0.964327 setdiff1d 1.352828 1.274061 1.483380 1.459986 1.466575 setdifflst 1.233332 1.444521 1.714199 1.797241 1.876425 ridx columndrop 0.903013 0.832814 0.949234 0.976366 0.982888 comprehension 0.777445 0.827151 1.108028 3.473164 25.528879 difference 1.086859 1.081396 1.293132 1.173044 1.237613 setdiff1d 0.946009 0.873169 0.900185 0.908194 1.036124 setdifflst 0.732964 0.823218 0.819748 0.990315 1.050910 ridxa columndrop 0.835254 0.774701 0.907105 0.908006 0.932754 comprehension 0.697749 0.762556 1.215225 3.510226 25.041832 difference 1.055099 1.010208 1.122005 1.119575 1.383065 setdiff1d 0.760716 0.725386 0.849949 0.879425 0.946460 setdifflst 0.710008 0.668108 0.778060 0.871766 0.939537 slc columndrop 1.268191 1.521264 2.646687 1.919423 1.981091 comprehension 0.856893 0.870365 1.290730 3.564219 26.208937 difference 1.470095 1.747211 2.886581 2.254690 2.050536 setdiff1d 1.098427 1.133476 1.466029 2.045965 3.123452 setdifflst 0.833700 0.846652 1.013061 1.110352 1.287831

fig, axes = plt.subplots(2, 2, figsize=(8, 6), sharey=True) for i, (n, g) in enumerate([(n, g.xs(n)) for n, g in rs.groupby(''Select'')]): ax = axes[i // 2, i % 2] g.plot.bar(ax=ax, title=n) ax.legend_.remove() fig.tight_layout()

Esto es relativo al tiempo que lleva ejecutar df.drop(dlst, 1, errors=''ignore'') . Parece que después de todo ese esfuerzo, solo mejoramos modestamente el rendimiento.

Si es el caso, las mejores soluciones utilizan reindex_axis o reindex_axis en la list(set(df.columns.values.tolist()).difference(dlst)) . Un segundo cercano y aún muy marginalmente mejor que el drop es np.setdiff1d .

rs.idxmin().pipe( lambda x: pd.DataFrame( dict(idx=x.values, val=rs.lookup(x.values, x.index)), x.index ) ) idx val 10 (ridx, setdifflst) 0.653431 30 (ridxa, setdifflst) 0.746143 100 (ridxa, setdifflst) 0.816207 300 (ridx, setdifflst) 0.780157 1000 (ridxa, setdifflst) 0.861622


Caer por índice

Eliminar primera, segunda y cuarta columnas:

df.drop(df.columns[[0,1,3]], axis=1, inplace=True)

Eliminar primera columna:

df.drop(df.columns[[0]], axis=1, inplace=True)

Hay un parámetro opcional en el inplace para que los datos originales puedan modificarse sin crear una copia.

Popped

Selección de columnas, adición, eliminación

Eliminar columna column-name :

df.pop(''column-name'')

Ejemplos:

df = DataFrame.from_items([(''A'', [1, 2, 3]), (''B'', [4, 5, 6]), (''C'', [7,8, 9])], orient=''index'', columns=[''one'', ''two'', ''three''])

print df :

one two three A 1 2 3 B 4 5 6 C 7 8 9

df.drop(df.columns[[0]], axis=1, inplace=True) print df :

two three A 2 3 B 5 6 C 8 9

three = df.pop(''three'') print df :

two A 2 B 5 C 8


A partir de la versión 0.16.1 se puede hacer.

df.drop([''column_name''], axis = 1, inplace = True, errors = ''ignore'')


En pandas 0.16.1+ puede eliminar columnas solo si existen según la solución publicada por @eiTanLaVi. Antes de esa versión, puede lograr el mismo resultado a través de una lista de comprensión condicional:

df.drop([col for col in [''col_name_1'',''col_name_2'',...,''col_name_N''] if col in df], axis=1, inplace=True)


Es difícil hacer que del df.column_name funcione simplemente como resultado de las limitaciones sintácticas en Python. del df[name] se traduce a df.__delitem__(name) bajo las carátulas de Python.


Es una buena práctica usar siempre la notación [] . Una razón es que la notación de atributo ( df.column_name ) no funciona para los índices numerados:

In [1]: df = DataFrame([[1, 2, 3], [4, 5, 6]]) In [2]: df[1] Out[2]: 0 2 1 5 Name: 1 In [3]: df.1 File "<ipython-input-3-e4803c0d1066>", line 1 df.1 ^ SyntaxError: invalid syntax


La mejor manera de hacer esto en pandas es usar drop :

df = df.drop(''column_name'', 1)

donde 1 es el número del eje ( 0 para filas y 1 para columnas).

Para eliminar la columna sin tener que reasignar df puede hacer:

df.drop(''column_name'', axis=1, inplace=True)

Finalmente, para colocar por número de columna en lugar de por etiqueta de columna, intente esto para eliminar, por ejemplo, las columnas 1, 2 y 4:

df.drop(df.columns[[0, 1, 3]], axis=1) # df.columns is zero-based pd.Index


La pregunta real planteada, perdida por la mayoría de las respuestas aquí es:

¿Por qué no puedo usar del df.column_name ?

Al principio debemos entender el problema, que requiere que nos sumergamos en los métodos mágicos de los pitones .

Como lo señala Wes en su respuesta del df[''column''] asigna al método mágico de python df.__delitem__(''column'') que se implementa en pandas para eliminar la columna

Sin embargo, como se señaló en el enlace anterior sobre los métodos mágicos de Python :

De hecho, dell casi nunca debe usarse debido a las precarias circunstancias en que se llama; ¡Úsalo con precaución!

Podría argumentar que del df[''column_name''] no se debe usar o alentar, y por lo tanto del df.column_name ni siquiera se debe considerar.

Sin embargo, en teoría, del df.column_name podría del df.column_name para trabajar en pandas usando el método mágico __delattr__ . Sin embargo, esto introduce ciertos problemas, problemas que ya tiene la implementación del df[''column_name''] , pero en menor grado.

Problema de ejemplo

¿Qué pasa si defino una columna en un marco de datos llamado "dtypes" o "columnas".

Entonces asume que quiero eliminar estas columnas.

del df.dtypes confundiría el método __delattr__ como si eliminara el atributo "dtypes" o la columna "dtypes".

Preguntas arquitectónicas detrás de este problema.

  1. ¿Es un marco de datos una colección de columnas ?
  2. ¿Es un marco de datos una colección de filas ?
  3. ¿Es una columna un atributo de un marco de datos?

Pandas responde:

  1. Si en todos los sentidos
  2. No, pero si lo desea, puede usar los .ix , .loc o .iloc .
  3. Tal vez, ¿quieres leer datos? Entonces , a menos que el nombre del atributo ya esté tomado por otro atributo que pertenece al marco de datos. ¿Quieres modificar los datos? Entonces no

TLDR;

No puede hacer del df.column_name porque pandas tiene una arquitectura bastante desarrollada que debe reconsiderarse para que este tipo de disonancia cognitiva no ocurra a sus usuarios.

Protip:

No use df.column_name, puede ser bonito, pero causa disonancia cognitiva

Cotizaciones de Zen de Python que encaja aquí:

Hay varias formas de eliminar una columna.

Debe haber una, y preferiblemente solo una, obvia forma de hacerlo.

Las columnas son a veces atributos pero a veces no.

Los casos especiales no son lo suficientemente especiales para romper las reglas.

¿ del df.dtypes elimina el atributo dtypes o la columna dtypes?

Ante la ambigüedad, rechace la tentación de adivinar.


La sintaxis de puntos funciona en JavaScript, pero no en Python.

  • Python: del df[''column_name'']
  • JavaScript: del df[''column_name''] o del df.column_name

Si desea eliminar una sola columna ( col_name ) desde un marco de datos ( df ), intente uno de los siguientes:

df = df.drop(col_name, axis=1)

O

df.drop(col_name, axis=1, inplace=True)

Si desea eliminar una lista de columnas ( col_lst = [col_name_1,col_name_2,...] ) de un marco de datos ( df ), intente uno de los siguientes:

df.drop(col_lst, axis=1, inplace=True)

O

df.drop(columns=col_lst, inplace=True)


Una buena adición es la capacidad de eliminar columnas solo si existen . De esta manera puede cubrir más casos de uso, y solo eliminará las columnas existentes de las etiquetas que se le pasaron:

Simplemente agregue errores = ''ignorar'' , por ejemplo .:

df.drop([''col_name_1'', ''col_name_2'', ..., ''col_name_N''], inplace=True, axis=1, errors=''ignore'')

  • Esto es nuevo a partir de pandas 0.16.1 en adelante. La documentación está here .

Utilizar:

columns = [''Col1'', ''Col2'', ...] df.drop(columns, inplace=True, axis=1)

Esto eliminará una o más columnas en el lugar. Tenga en cuenta que inplace=True se agregó en pandas v0.13 y no funcionará en versiones anteriores. Tendrías que volver a asignar el resultado en ese caso:

df = df.drop(columns, axis=1)


Otra forma de eliminar una columna en Pandas DataFrame

Si no está buscando una eliminación in situ, puede crear un nuevo DataFrame especificando las columnas usando la función DataFrame(...) como

my_dict = { ''name'' : [''a'',''b'',''c'',''d''], ''age'' : [10,20,25,22], ''designation'' : [''CEO'', ''VP'', ''MD'', ''CEO'']} df = pd.DataFrame(my_dict)

Crear un nuevo DataFrame como

newdf = pd.DataFrame(df, columns=[''name'', ''age''])

Obtienes un resultado tan bueno como lo que obtienes con del / drop