Seleccionar / Excluir conjuntos de columnas en Pandas


Me gustaría crear vistas o dataframes a partir de un dataframe existente basado en selecciones de columnas.

Por ejemplo, me gustaría crear un dataframe df2 a partir de un dataframe df1 que contenga todas las columnas excepto dos de ellas. Intenté hacer lo siguiente, pero no funcionó:

import numpy as np
import pandas as pd

# Create a dataframe with columns A,B,C and D
df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))

# Try to create a second dataframe df2 from df with all columns except 'B' and D
my_cols = set(df.columns)
my_cols.remove('B').remove('D')

# This returns an error ("unhashable type: set")
df2 = df[my_cols]

¿Qué estoy haciendo mal? Quizás de manera más general, ¿qué mecanismos tiene Panda para soportar la selección y exclusiones de conjuntos arbitrarios de columnas de un dataframe?

 155
Author: Amelio Vazquez-Reina, 2013-02-18

9 answers

Puede soltar las columnas que no necesita O Seleccionar las que necesita

# Using DataFrame.drop
df.drop(df.columns[[1, 2]], axis=1, inplace=True)

# drop by Name
df1 = df1.drop(['B', 'C'], axis=1)

# Select the ones you want
df1 = df[['a','d']]
 222
Author: Amrita Sawant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-12 16:16:58

Hay un nuevo método de índice llamado difference. Devuelve las columnas originales, con las columnas pasadas como argumento eliminadas.

df2 = df[df.columns.difference(['B', 'D'])]

Aquí, la salida se usa para filtrar las columnas B y D de df.

 96
Author: IanS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-16 08:34:48

Realmente no necesitas convertir eso en un conjunto:

cols = [col for col in df.columns if col not in ['B', 'D']]
df2 = df[cols]
 51
Author: piggybox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-18 02:25:39

También echar un vistazo a la incorporada DataFrame.filter función.

Enfoque minimalista pero codicioso (suficiente para el df dado):

df.filter(regex="[^BD]")

Enfoque conservador / perezoso (solo coincidencias exactas):

df.filter(regex="^(?!(B|D)$).*$")

Conservador y genérico:

exclude_cols = ['B','C']
df.filter(regex="^(?!({0})$).*$".format('|'.join(exclude_cols)))
 13
Author: Frank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-14 09:02:31

Solo necesita convertir su set a un list

import pandas as pd
df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))
my_cols = set(df.columns)
my_cols.remove('B')
my_cols.remove('D')
my_cols = list(my_cols)
df2 = df[my_cols]
 6
Author: tacaswell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-18 16:32:43

He aquí cómo crear una copia de una DataFrame excluyendo una lista de columnas:

df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))
df2 = df.drop(['B', 'D'], axis=1)

Pero ten cuidado! Mencionas puntos de vista en tu pregunta, sugiriendo que si cambiaste df, querrías que df2 también cambiara. (Como lo haría una vista en una base de datos.)

Este método no logra eso:

>>> df.loc[0, 'A'] = 999 # Change the first value in df
>>> df.head(1)
     A         B         C         D
0  999 -0.742688 -1.980673 -0.920133
>>> df2.head(1) # df2 is unchanged. It's not a view, it's a copy!
          A         C
0  0.251262 -1.980673

Tenga en cuenta también que esto también es cierto para el método de @piggybox. (Aunque ese método es agradable y hábil y Pitónico. ¡No lo estoy haciendo mal!!)

Para más información sobre vistas vs. copias ver esta respuesta y esta parte de los documentos de Pandas a la que se refiere esa respuesta.

 4
Author: LondonRob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:21

Tienes 4 columnas A,B,C, D

Aquí hay una mejor manera de seleccionar las columnas que necesita para el nuevo dataframe: -

df2 = df1[['A','D']]

Si desea usar números de columna en su lugar, use: -

df2 = df1[[0,3]]
 2
Author: Kapil Marwaha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-18 13:56:12

Otra opción, sin dejar caer o filtrar en un bucle:

import numpy as np
import pandas as pd

# Create a dataframe with columns A,B,C and D
df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))

# include the columns you want
df[df.columns[df.columns.isin(['A', 'B'])]]

# exclude columns you don't want
df[df.columns[~df.columns.isin(['C','D'])]]
 2
Author: MrE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-30 20:41:25

En una línea similar, al leer un archivo, uno puede desear excluir columnas por adelantado, en lugar de leer desperdiciadamente datos no deseados en la memoria y luego descartarlos.

A partir de pandas 0.20.0, usecols ahora acepta callables .1 Esta actualización permite opciones más flexibles para leer columnas:

skipcols = [...]
read_csv(..., usecols=lambda x: x not in skipcols)

El último patrón es esencialmente el inverso del método tradicional usecols - solo las columnas especificadas son saltar.


Dado

Datos en un archivo

import numpy as np
import pandas as pd


df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))

filename = "foo.csv"
df.to_csv(filename)

Código

skipcols = ["B", "D"]
df1 = pd.read_csv(filename, usecols=lambda x: x not in skipcols, index_col=0)
df1

Salida

          A         C
0  0.062350  0.076924
1 -0.016872  1.091446
2  0.213050  1.646109
3 -1.196928  1.153497
4 -0.628839 -0.856529
...

Detalles

Se escribió un DataFrame en un archivo. Luego se volvió a leer como un DataFrame separado, ahora saltando columnas no deseadas (B y D).

Tenga en cuenta que para la situación del OP, ya que los datos ya están creados, el mejor enfoque es la respuesta aceptada, que elimina columnas no deseadas de un objeto existente. Obstante, la técnica presentada aquí es más útil cuando se leen directamente datos de archivos en un DataFrame.

En esta cuestión se formuló una solicitud de opción "skipcols", que se abordó en una cuestión posterior .

 1
Author: pylang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-04 17:32:26