2013-02-18 5 views
110

Я хотел был бы создать взгляды или dataframes от существующего dataframe на основе выбора столбцов.Выбор/исключение наборов столбцов в Pandas

Например, я хотел бы создать dataframe df2 из dataframe df1, который содержит все столбцы, кроме двух из них. Я пробовал делать следующее, но это не помогло:

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] 

Что я делаю неправильно? Возможно, в более общем плане, какие механизмы Panda должны поддерживать сбор и исключений произвольных наборов столбцов из фрейма данных?

+1

возможно дубликат [Удалить столбец из панд DataFrame] (http://stackoverflow.com/questions/13411544/delete-column-from-pandas-dataframe) –

ответ

157

Вы можете либо удалить столбцы, которые вам не нужны, либо выбрать один S вам нужно

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

есть ли способ просто выбрать столбец 'n''th? т.е.: 'df1 = my_df [[n]]' где _n_ - последний столбец из числа столбцов _n_, я пытаюсь отрицательно индексировать '[[-1]]' <- он не работает :(help! ~ – 3kstc

5

Вам просто нужно конвертировать ваши set в 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

Спасибо! Это работает отлично. Просто интересно, есть ли какие-либо функции в Panda, которые облегчают спецификацию столбцов для этого типа (или более сложных типов) фильтрации столбцов? –

+0

@ user273158 Не знаю, я только начинаю изучать «Панды». – tacaswell

+3

Возможно использование [drop] (http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.drop.html?highlight=drop#pandas.DataFrame.drop) ?. 'df.drop (my_cols, axis = 1)' будет вызывать представление DataFrame с отброшенными столбцами. Все, что вам нужно, - это назначить его новому DF: 'df2 = df.drop (my_cols, axis = 1)' – herrfz

48

Вы на самом деле не нужно, чтобы преобразовать его в набор:

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

Вот как создать копию из a DataFrame, за исключением перечня колонок:

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

Но будьте осторожны! Вы указываете мнения в своем вопросе, предлагая, чтобы, если вы изменили df, вам нужно также изменить df2. (. Как бы представления в базе данных)

Этот метод не добиться того, что:

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

Заметим также, что это также относится метод @ piggybox в. (Хотя этот метод приятный и гладкий и Pythonic. Я не делаю это!)

Подробнее о просмотрах и копиях см. this SO answer и this part of the Pandas docs, к которому относится этот ответ.

11

Также обратите внимание на встроенную функцию DataFrame.filter.

Минималистичный, но жадный подход (достаточный для данного DF):

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

Консервативная/ленивым подход (точное совпадение только):

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

Консервативное и родовое:

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

Существует новый индексный метод называется difference. Он возвращает исходные столбцы, при этом столбцы передаются как аргумент.

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

Здесь выходной сигнал используется для фильтрации столбцов B и D от df.

+2

Хорошее. Есть ли преимущество/недостаток в том, чтобы делать это таким образом в сравнении с 'df.drop (['B', 'D'], axis = 1)'? – Ben

+1

Для меня преимущество - читаемость кода. 'drop', чтобы выбрать столбцы, интуитивно понятные. – IanS

+3

' difference() 'также, похоже, упорядочивает столбцы по алфавиту по умолчанию – slizb

0

В том же духе, при чтении файла, многие хотят исключить столбцы, а не расточительно считывать нежелательные данные в память и затем отбрасывать их.

с учетом pandas 0.20.0, usecols now accepts callables. Это обновление позволяет более гибкие возможности для чтения столбцов:

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

Последняя модель является по существу инверсией традиционного метода usecols - только указанные столбцы пропускаются.


Учитывая

данных в файле

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) 

Код

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

Выход

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

Подробности

DataFrame был записан в файл и считаны как отдельные DataFrame, теперь пропуская ненужные столбцы.

Обратите внимание, что для ситуации с ОП, поскольку данные уже созданы, лучшим подходом является принятый ответ, который отбрасывает нежелательные столбцы из объекта-объекта. Однако представленная здесь методика наиболее полезна при прямом чтении данных из файлов в DataFrame.

Запрос был поднят вариант «skipcols» в this issue и был рассмотрен в более позднем issue.

Смежные вопросы