2013-02-18 9 views
110

Ich möchte Ansichten oder Datenrahmen aus einem vorhandenen Datenrahmen basierend auf Spaltenauswahlen erstellen.Auswählen/Ausschließen von Spaltengruppen in Pandas

Zum Beispiel möchte ich einen Datenrahmen df2 von einem Datenrahmen df1 erstellen, der alle Spalten enthält, außer zwei davon. Ich habe Folgendes versucht, aber es hat nicht funktioniert:

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] 

Was mache ich falsch? Vielleicht allgemeiner, welche Mechanismen muss Panda die Auswahl und Ausschlüsse beliebiger Spalten von einem Dataframe unterstützen?

+1

möglich Duplikat von [Spalte aus Pandas DataFrame löschen] (http://stackoverflow.com/questions/13411544/delete-column-from-pandas-dataframe) –

Antwort

157

Sie können entweder die Spalten löschen, die Sie nicht benötigen ODER Wählen Sie die eine aus s Sie

##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']] 
+0

gibt es einen Weg nur die Spalte "n" auszuwählen? zB: 'df1 = my_df [[n]]' wobei _n_ die letzte Spalte von _n_ column ist, versuche ich eine negative Indizierung '[[-1]]' <- es funktioniert nicht :(help! ~ – 3kstc

5

Sie müssen nur Ihre set zu einem 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] 
+0

Vielen Dank! Das funktioniert ganz gut. Ich frage mich nur, gibt es irgendwelche Funktionen in Panda, die die Spezifikation von Spalten für diesen Typ (oder komplexere Typen) der Spaltenfilterung erleichtern? –

+0

@ user273158 Ich weiß nicht, ich fange gerade an, 'Pandas' zu lernen. – tacaswell

+3

Vielleicht verwenden Sie [drop] (http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.drop.html?highlight=drop#pandas.DataFrame.drop) ?. 'df.drop (my_cols, axis = 1)' erzeugt eine Ansicht des DataFrame mit den gelöschten Spalten. Alles, was Sie brauchen, ist dann, es dem neuen DF zuzuweisen: 'df2 = df.drop (my_cols, axis = 1)' – herrfz

48

Sie haben nicht wirklich, dass in einen Satz konvertieren müssen konvertieren:

cols = [col for col in df.columns if col not in ['B', 'D']] 
df2 = df[cols] 
4

Hier ist, wie eine Kopie erstellen von a DataFrame mit Ausnahme einer Spaltenliste:

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

Aber Vorsicht! Sie erwähnen Ansichten in Ihrer Frage und schlagen vor, dass Sie, wenn Sie df geändert haben, auch df2 ändern möchten. (. Wie ein Blick würde in einer Datenbank)

Diese Methode erreicht nicht, dass:

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

Beachten Sie auch, dass diese von @ piggybox Methode auch wahr ist. (Obwohl diese Methode ist schön und glatt und Pythonic. Ich mache es nicht nach unten!)

Für weitere Ansichten vs Kopien siehe this SO answer und this part of the Pandas docs, auf die sich diese Antwort bezieht.

11

Schauen Sie auch in die eingebaute DataFrame.filter Funktion.

Minimalistic aber gierig Ansatz (ausreichend für die gegebene df):

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

Konservativ/faul Ansatz (genaue Übereinstimmung nur):

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

Konservative und generic:

exclude_cols = ['B','C'] 
df.filter(regex="^(?!({0})$).*$".format('|'.join(exclude_cols))) 
76

Es gibt eine neue Index-Methode namens difference benötigen. Es gibt die ursprünglichen Spalten zurück, wobei die Spalten als Argument entfernt übergeben wurden.

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

Hier wird der Ausgang B und D von df zum Ausfiltern von Säulen verwendet.

+2

Nice.Es gibt einen Vorteil/Nachteil, dies auf diese Weise zu tun gegenüber "df.drop (['B', 'D'], Achse = 1)'? – Ben

+1

Für mich ist der Vorteil der Code Lesbarkeit. Ich finde die Verwendung von 'drop' zum Auswählen von Spalten kontraintuitiv – IanS

+3

' difference() 'scheint auch Spalten alphabetisch standardmäßig zu referenzieren – slizb

0

In ähnlicher Weise, wenn Sie eine Datei lesen, möchte man viele Spalten im Voraus ausschließen, anstatt verschwenderisch unerwünschte Daten in den Speicher zu lesen und später zu verwerfen.

Ab Pandabären 0.20.0, usecols now accepts callables. Dieses Update ermöglicht eine flexiblere Optionen für das Lesen von Spalten:

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

Letztere Muster ist im wesentlichen die Umkehrung der traditionellen usecols Methode - nur bestimmte Spalten übersprungen werden.


Daten in einer Datei

Gegeben
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 

Ausgabe

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

Einzelheiten

Der Datenrahmen wurde in eine Datei geschrieben und wieder als separater Datenrahmen, jetzt Überspringen unerwünschte Spalten lesen.

Beachten Sie, dass für die Situation des OP, da Daten bereits erstellt werden, der bessere Ansatz die akzeptierte Antwort ist, die unerwünschte Spalten von einem vorhandenen Objekt löscht. Die hier vorgestellte Technik ist jedoch am nützlichsten, wenn Daten direkt aus Dateien in einen DataFrame gelesen werden.

wurde eine Anforderung in this issue für eine "skipcols" Option angehoben und wurde in einer neueren issue gerichtet.