Sélection / exclusion des ensembles de colonnes dans les Pandas

Je voudrais créer des vues ou des dataframes à partir d'un dataframe existant en fonction des sélections de colonnes.

Par exemple, je voudrais créer un DataFrame df2 à partir d'un DataFrame df1 qui contient toutes les colonnes sauf deux d'entre elles. J'ai essayé de faire ce qui suit, mais cela n'a pas fonctionné:

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'est-ce que je fais de mal? Peut-être plus généralement, quels mécanismes Panda a-t-il pour prendre en charge la sélection et exclusions d'ensembles arbitraires de colonnes à partir d'un dataframe?

155
demandé sur Amelio Vazquez-Reina 2013-02-18 20:22:38

9 réponses

Vous pouvez soit supprimer les colonnes dont vous n'avez pas besoin, soit sélectionner celles dont vous avez besoin

# 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
répondu Amrita Sawant 2018-06-12 16:16:58

Il existe une nouvelle méthode d'index appelée difference. Il renvoie les colonnes d'origine, avec les colonnes passées comme argument supprimé.

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

Ici, la sortie est utilisée pour filtrer les colonnes B et D de df.

96
répondu IanS 2016-08-16 08:34:48

Vous n'avez pas vraiment besoin de convertir cela en un ensemble:

cols = [col for col in df.columns if col not in ['B', 'D']]
df2 = df[cols]
51
répondu piggybox 2013-11-18 02:25:39

Ont Également un coup d'oeil dans le haut-DataFrame.filter fonction.

Approche minimaliste mais gourmande (suffisante pour le df donné):

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

Approche conservatrice / paresseuse (correspondances exactes uniquement):

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

Conservateur et générique:

exclude_cols = ['B','C']
df.filter(regex="^(?!({0})$).*$".format('|'.join(exclude_cols)))
13
répondu Frank 2014-10-14 09:02:31

, Vous avez juste besoin de convertir votre set pour 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
répondu tacaswell 2013-02-18 16:32:43

Voici comment créer un copie de DataFrame à l'exclusion d'une liste de colonnes:

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

Mais attention! Vous mentionnez les vues dans votre question, suggérant que si vous avez changé df, vous voudriez que df2 change aussi. (Comme une vue dans une base de données.)

Cette méthode n'atteint pas cela:

>>> 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

Notez également que cela est également vrai de la méthode de @ piggybox. (Bien que cette méthode soit agréable et lisse et pythonique. Je ne vais pas le faire vers le bas!!)

Pour en savoir plus sur les vues et les copies voir cette réponse SO et cette partie des documents Pandas auxquels cette réponse fait référence.

4
répondu LondonRob 2017-05-23 12:18:21

Vous avez 4 colonnes A,B,C, D

Voici une meilleure façon de sélectionner les colonnes dont vous avez besoin pour le nouveau dataframe: -

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

Si vous souhaitez utiliser des numéros de colonne à la place, Utilisez: -

df2 = df1[[0,3]]
2
répondu Kapil Marwaha 2018-06-18 13:56:12

Une autre option, sans laisser tomber ou filtrer dans une boucle:

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
répondu MrE 2018-07-30 20:41:25

Dans la même veine, lors de la lecture d'un fichier, on peut souhaiter exclure des colonnes dès le départ, plutôt que de lire inutilement des données indésirables en mémoire et de les rejeter plus tard.

, Comme des pandas 0.20.0, usecols accepte maintenant callables.1 Cette mise à jour permet des options plus flexibles pour la lecture des colonnes:

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

Ce dernier modèle est essentiellement l'inverse de la méthode traditionnelle usecols - seules les colonnes spécifiées sont sauter.


Compte tenu de

Données dans un fichier

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)

Code

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

Sortie

          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
...

Détails

Un DataFrame a été écrit dans un fichier. Il a ensuite été relu comme un DataFrame séparé, sautant maintenant les colonnes indésirables (B et D).

Notez que pour la situation de L'OP, puisque les données sont déjà créées, la meilleure approche est la réponse acceptée, qui supprime les colonnes indésirables d'un objet existant. Cependant, la technique présentée ici est très utile lors de la lecture directe de données à partir de fichiers dans un DataFrame.

Une demande a été posée par "skipcols" option dans cette question et a été résolu dans une version ultérieure question.

1
répondu pylang 2018-06-04 17:32:26