Выбор нескольких столбцов в кадре данных pandas

1114

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

index  a   b   c
1      2   3   4
2      3   4   5

Как выбрать 'a', 'b'и сохранить его , чтобы df1?

Я старался

df1 = df['a':'b']
df1 = df.ix[:, 'a':'b']

Никто, кажется, не работает.

user1234440
источник
2
Вы никогда не хотите использовать, .ixпоскольку это неоднозначно. Используйте .ilocили, .locесли вы должны.
Acumenus
1
Есть ли способ сделать это, не обращаясь к именам заголовков? как и в R, я могу сделать это следующим образом: > csvtable_imp_1 <- csvtable_imp[0:6]и он выбирает величину дельты в первых столбцах от 0 до 6. Все, что мне нужно было сделать, это прочитать таблицу csv, разделенную библиотекой readr.
MichaelR
Я работал немного больше с этим. Нашел то, что работало так, как хотел. По умолчанию выбираются числа символов, а не столбцов. infile_1 = largefile_stay.ix[:,0:6]
MichaelR
3
Для тех, кто спотыкается об этом поздно, ixсейчас не рекомендуется. Pandas рекомендует использовать либо: loc(индексация на основе меток), либо iloc(позиционная индексация).
ЗайдХ

Ответы:

1773

Имена столбцов (которые являются строками) не могут быть разрезаны так, как вы пытались.

Здесь у вас есть несколько вариантов. Если вы знаете из контекста, какие переменные вы хотите вырезать, вы можете просто вернуть представление только этих столбцов, передав список в __getitem__синтаксис ([]).

df1 = df[['a','b']]

Или же, если имеет значение индексировать их численно, а не по их имени (скажем, ваш код должен делать это автоматически, не зная имен первых двух столбцов), тогда вы можете сделать это вместо этого:

df1 = df.iloc[:,0:2] # Remember that Python does not slice inclusive of the ending index.

Кроме того, вы должны ознакомиться с идеей представления объекта Pandas вместо его копии. Первый из вышеперечисленных методов вернет новую копию в память нужного подобъекта (желаемых фрагментов).

Однако иногда в Pandas существуют соглашения об индексировании, которые этого не делают и вместо этого дают новую переменную, которая просто ссылается на тот же кусок памяти, что и субобъект или фрагмент исходного объекта. Это произойдет со вторым способом индексации, поэтому вы можете изменить его с помощью copy()функции, чтобы получить обычную копию. Когда это происходит, изменение того, что вы считаете разрезанным объектом, иногда может изменить исходный объект. Всегда хорошо быть настороже.

df1 = df.iloc[0,0:2].copy() # To avoid the case where changing df1 also changes df

Чтобы использовать iloc, вам нужно знать позиции столбцов (или индексы). Поскольку позиции столбцов могут изменяться, вместо жестко кодированных индексов вы можете использовать ilocвместе с get_locфункцией columnsметода объекта dataframe для получения индексов столбцов.

{df.columns.get_loc(c):c for idx, c in enumerate(df.columns)}

Теперь вы можете использовать этот словарь для доступа к столбцам через имена и использование iloc.

Ely
источник
192
Примечание: df[['a','b']]выдает копию
Уэс МакКинни
1
Да, это было скрыто в моем ответе. Бит о копии был только для использования, ix[]если вы предпочитаете использовать ix[]по любой причине.
Ely
1
ixиндексирует строки, а не столбцы. Я думал, что ОП хотел столбцы.
варенье
9
ixпринимает аргументы среза, поэтому вы также можете получить столбцы. Например, df.ix[0:2, 0:2]получает верхний левый подмассив 2x2, как это делается для матрицы NumPy (конечно, в зависимости от имен столбцов). Вы даже можете использовать синтаксис среза для строковых имен столбцов, например df.ix[0, 'Col1':'Col5']. Это получает все столбцы, которые, как оказалось, упорядочены между Col1и Col5в df.columnsмассиве. Неверно говорить, что ixиндексирует строки. Это всего лишь его основное использование. Он также поддерживает гораздо больше индексации, чем это. Итак, ixявляется совершенно общим для этого вопроса.
Ely
7
@AndrewCassidy Никогда не используйте .ix снова. Если вы хотите нарезать целыми числами, используйте .ilocисключающую последнюю позицию, как списки Python.
Тед Петру
133

Начиная с версии 0.11.0 столбцы можно разрезать так, как вы пытались использовать .locиндексатор:

df.loc[:, 'C':'E']

эквивалентно

df[['C', 'D', 'E']]  # or df.loc[:, ['C', 'D', 'E']]

и возвращает столбцы Cчерез E.


Демонстрация случайно сгенерированного DataFrame:

import pandas as pd
import numpy as np
np.random.seed(5)
df = pd.DataFrame(np.random.randint(100, size=(100, 6)), 
                  columns=list('ABCDEF'), 
                  index=['R{}'.format(i) for i in range(100)])
df.head()

Out: 
     A   B   C   D   E   F
R0  99  78  61  16  73   8
R1  62  27  30  80   7  76
R2  15  53  80  27  44  77
R3  75  65  47  30  84  86
R4  18   9  41  62   1  82

Чтобы получить столбцы от C до E (обратите внимание, что в отличие от целочисленной нарезки 'E' включено в столбцы):

df.loc[:, 'C':'E']

Out: 
      C   D   E
R0   61  16  73
R1   30  80   7
R2   80  27  44
R3   47  30  84
R4   41  62   1
R5    5  58   0
...

То же самое работает для выбора строк на основе меток. Получите строки 'R6' до 'R10' из этих столбцов:

df.loc['R6':'R10', 'C':'E']

Out: 
      C   D   E
R6   51  27  31
R7   83  19  18
R8   11  67  65
R9   78  27  29
R10   7  16  94

.locтакже принимает логический массив, чтобы вы могли выбрать столбцы, чья соответствующая запись в массиве True. Например, df.columns.isin(list('BCD'))возвращает array([False, True, True, True, False, False], dtype=bool)- True, если имя столбца находится в списке ['B', 'C', 'D']; Ложно, иначе.

df.loc[:, df.columns.isin(list('BCD'))]

Out: 
      B   C   D
R0   78  61  16
R1   27  30  80
R2   53  80  27
R3   65  47  30
R4    9  41  62
R5   78   5  58
...
Айхан
источник
110

Предполагая, что ваши имена столбцов ( df.columns) ['index','a','b','c'], то данные, которые вы хотите, находятся в 3-м и 4-м столбцах. Если вы не знаете их имен при запуске скрипта, вы можете сделать это

newdf = df[df.columns[2:4]] # Remember, Python is 0-offset! The "3rd" entry is at slot 2.

Как указывает EMS в своем ответе , df.ixстолбцы срезаются немного более кратко, но .columnsинтерфейс среза может быть более естественным, поскольку он использует ванильный 1-D синтаксис индексации / среза списка Python.

ВНИМАНИЕ: 'index'это плохое имя для DataFrameстолбца. Эта же метка также используется для реального df.indexатрибута, Indexмассива. Таким образом, ваш столбец возвращается, df['index']а реальный индекс DataFrame - df.index. An Index- это особый вид, Seriesоптимизированный для поиска значений его элементов. Для df.index это поиск строк по их меткам. Этот df.columnsатрибут также является pd.Indexмассивом для поиска столбцов по их меткам.

варочные панели
источник
3
Как я отметил в моем комментарии выше, .ixэто не только для строк. Он предназначен для нарезки общего назначения и может использоваться для многомерного среза. По сути, это просто интерфейс к обычному __getitem__синтаксису NumPy . Тем не менее, вы можете легко преобразовать проблему нарезки столбцов в задачу нарезки строк, просто применив операцию транспонирования df.T. Ваш пример использует columns[1:3], что немного вводит в заблуждение. Результатом columnsявляется Series; будьте осторожны, чтобы не относиться к нему как к массиву. Кроме того, вам, вероятно, следует изменить его, чтобы он columns[2:3]соответствовал вашему 3-му и 4-му комментарию.
Ely
@ Mr.F: Мой [2:4]правильно. Вы [2:3]не правы. И использование стандартной нотации Python для создания последовательности / Series не вводит в заблуждение IMO. Но мне нравится ваш обход интерфейса DataFrame для доступа к базовому массиву numpy ix.
варенье
В этом случае вы правы, но я хотел подчеркнуть, что нарезка с метками в Pandas включает конечную точку среза (или, по крайней мере, так было в большинстве предыдущих версий Pandas). Так что если вы извлекаете df.columnsи хотите разрезать его по метке , то у вас будет другая семантика слайса, чем если бы вы разрезали его по позиции целочисленного индекса . Я определенно не объяснил это хорошо в моем предыдущем комментарии все же.
Ely
Ааа, теперь я понимаю вашу точку зрения. Я забыл, что columnsэто неизменная серия, и получатель был переопределен для использования меток в качестве индексов. Спасибо, что нашли время, чтобы уточнить.
варочные панели
2
Обратите внимание на предупреждение об устаревании: .ix устарела. Поэтому это имеет смысл: newdf = df [df.columns [2: 4]]
Мартиен Лубберинк,
64
In [39]: df
Out[39]: 
   index  a  b  c
0      1  2  3  4
1      2  3  4  5

In [40]: df1 = df[['b', 'c']]

In [41]: df1
Out[41]: 
   b  c
0  3  4
1  4  5
Уэс МакКинни
источник
1
Что если я захочу переименовать столбец, например, что-то вроде: df[['b as foo', 'c as bar']так, чтобы вывод переименовал столбец bкак fooи столбец cкак bar?
kuanb
5
df[['b', 'c']].rename(columns = {'b' : 'foo', 'c' : 'bar'})
Грег
62

Я понимаю, что этот вопрос довольно старый, но в последней версии панд есть простой способ сделать именно это. Имена столбцов (которые являются строками) могут быть нарезаны любым удобным для вас способом.

columns = ['b', 'c']
df1 = pd.DataFrame(df, columns=columns)
zerovector
источник
6
Это может быть сделано только при создании. Вопрос заключается в том, есть ли у вас это в кадре данных.
Banjocat
3
@Banjocat, он работает с существующим
фреймом данных
23

Вы можете предоставить список столбцов, которые нужно удалить, и вернуть обратно DataFrame, используя только те столбцы, которые необходимы, используя drop()функцию в Pandas DataFrame.

Просто говорю

colsToDrop = ['a']
df.drop(colsToDrop, axis=1)

вернул бы DataFrame только со столбцами bи c.

dropМетод документирован здесь .

Мутху Читхамбара Джоти
источник
23

С пандами,

названия столбцов остроумия

dataframe[['column1','column2']]

выбрать по iloc и конкретным столбцам с порядковым номером:

dataframe.iloc[:,[1,2]]

с именами столбцов loc можно использовать как

dataframe.loc[:,['column1','column2']]
Вивек Анантан
источник
20

Я нашел этот метод очень полезным:

# iloc[row slicing, column slicing]
surveys_df.iloc [0:3, 1:4]

Более подробную информацию можно найти здесь

Алвис
источник
Как бы вы взяли, скажем, только столбцы 2 и 5?
324
1
Это было бы surveys_df.iloc [:, [2,5]]тогда.
Джулиан Горфер
15

Начиная с 0.21.0, использование .locили []со списком с одним или несколькими отсутствующими ярлыками не рекомендуется в пользу .reindex. Итак, ответ на ваш вопрос:

df1 = df.reindex(columns=['b','c'])

В предыдущих версиях использование .loc[list-of-labels]работало до тех пор, пока был найден хотя бы один из ключей (в противном случае он вызывал бы a KeyError). Это поведение устарело и теперь показывает предупреждение. Рекомендуемая альтернатива заключается в использовании .reindex().

Подробнее читайте в разделе «Индексирование и выбор данных»

tozCSS
источник
10

Вы можете использовать панд. Я создаю DataFrame:

    import pandas as pd
    df = pd.DataFrame([[1, 2,5], [5,4, 5], [7,7, 8], [7,6,9]], 
                      index=['Jane', 'Peter','Alex','Ann'],
                      columns=['Test_1', 'Test_2', 'Test_3'])

Фрейм данных:

           Test_1  Test_2  Test_3
    Jane        1       2       5
    Peter       5       4       5
    Alex        7       7       8
    Ann         7       6       9

Чтобы выбрать 1 или более столбцов по имени:

    df[['Test_1','Test_3']]

           Test_1  Test_3
    Jane        1       5
    Peter       5       5
    Alex        7       8
    Ann         7       9

Вы также можете использовать:

    df.Test_2

И вы получите столбец Test_2

    Jane     2
    Peter    4
    Alex     7
    Ann      6

Вы также можете выбрать столбцы и строки из этих строк, используя .loc(). Это называется "нарезка" . Обратите внимание, что я беру из столбца Test_1вTest_3

    df.loc[:,'Test_1':'Test_3']

«Срез» - это:

            Test_1  Test_2  Test_3
     Jane        1       2       5
     Peter       5       4       5
     Alex        7       7       8
     Ann         7       6       9

И если вы просто хотите , Peterи Annиз колонок Test_1и Test_3:

    df.loc[['Peter', 'Ann'],['Test_1','Test_3']]

Ты получаешь:

           Test_1  Test_3
    Peter       5       5
    Ann         7       9
pink.slash
источник
8

Если вы хотите получить один элемент по индексу строки и имени столбца, вы можете сделать это так же, как df['b'][0]. Это так просто, как вы можете себе представить.

Или вы можете использовать df.ix[0,'b']смешанное использование индекса и метки.

Примечание. Поскольку версия 0.20 ixустарела в пользу loc/ iloc.

W.Perrin
источник
6

Один другой и простой подход: итерация строк

используя iterows

 df1= pd.DataFrame() #creating an empty dataframe
 for index,i in df.iterrows():
    df1.loc[index,'A']=df.loc[index,'A']
    df1.loc[index,'B']=df.loc[index,'B']
    df1.head()
Ankita
источник
5
Пожалуйста, не рекомендуется использовать iterrows (). Это явный стимул самого плохого анти-паттерна в истории панд.
cs95
Не могли бы вы объяснить, что вы подразумеваете под «худшим анти-паттерном»?
Ankita
1
ИМХО, iterrows () должен быть последним вариантом при использовании панд.
Эльф
5

Различные подходы, рассмотренные в ответах выше, основаны на предположении, что либо пользователь знает индексы столбцов для отбрасывания или поднабора, либо пользователь желает установить подкадр данных с использованием диапазона столбцов (например, между «C»: «E») , pandas.DataFrame.drop () , безусловно , является возможность данных подмножества на основе списка столбцов , определенных пользователем (хотя вы должны быть осторожны , что вы всегда использовать копию dataframe и INPLACE параметры не должны быть установлены в значение True !!)

Другой вариант - использовать pandas.columns.difference () , который устанавливает различие в именах столбцов и возвращает индексный тип массива, содержащего нужные столбцы. Ниже приводится решение:

df = pd.DataFrame([[2,3,4],[3,4,5]],columns=['a','b','c'],index=[1,2])
columns_for_differencing = ['a']
df1 = df.copy()[df.columns.difference(columns_for_differencing)]
print(df1)

Выход будет: b c 1 3 4 2 4 5

Harshit
источник
1
Копия () не нужна. то есть: df1 = df[df.columns.difference(columns_for_differencing)]вернет новый / скопированный кадр данных. Вы сможете изменить df1без изменений df. Спасибо, кстати. Это было именно то, что мне было нужно.
Базили Дебовски
4

Вы также можете использовать df.pop ()

>>> df = pd.DataFrame([('falcon', 'bird',    389.0),
...                    ('parrot', 'bird',     24.0),
...                    ('lion',   'mammal',   80.5),
...                    ('monkey', 'mammal', np.nan)],
...                   columns=('name', 'class', 'max_speed'))
>>> df
     name   class  max_speed
0  falcon    bird      389.0
1  parrot    bird       24.0
2    lion  mammal       80.5
3  monkey  mammal 

>>> df.pop('class')
0      bird
1      bird
2    mammal
3    mammal
Name: class, dtype: object

>>> df
     name  max_speed
0  falcon      389.0
1  parrot       24.0
2    lion       80.5
3  monkey        NaN

дайте мне знать, если это поможет вам, пожалуйста, используйте df.pop (c)

Пунит Синха
источник
3

Я видел несколько ответов на этот вопрос, но он остался неясным для меня. Как бы вы выбрали эти столбцы интересов? Ответ заключается в том, что если они собраны в списке, вы можете просто ссылаться на столбцы, используя список.

пример

print(extracted_features.shape)
print(extracted_features)

(63,)
['f000004' 'f000005' 'f000006' 'f000014' 'f000039' 'f000040' 'f000043'
 'f000047' 'f000048' 'f000049' 'f000050' 'f000051' 'f000052' 'f000053'
 'f000054' 'f000055' 'f000056' 'f000057' 'f000058' 'f000059' 'f000060'
 'f000061' 'f000062' 'f000063' 'f000064' 'f000065' 'f000066' 'f000067'
 'f000068' 'f000069' 'f000070' 'f000071' 'f000072' 'f000073' 'f000074'
 'f000075' 'f000076' 'f000077' 'f000078' 'f000079' 'f000080' 'f000081'
 'f000082' 'f000083' 'f000084' 'f000085' 'f000086' 'f000087' 'f000088'
 'f000089' 'f000090' 'f000091' 'f000092' 'f000093' 'f000094' 'f000095'
 'f000096' 'f000097' 'f000098' 'f000099' 'f000100' 'f000101' 'f000103']

У меня есть следующий массив list / numpy extracted_features, указывающий 63 столбца. Исходный набор данных имеет 103 столбца, и я хотел бы извлечь именно те, то я бы использовал

dataset[extracted_features]

И вы закончите с этим

введите описание изображения здесь

Это то, что вы бы использовали довольно часто в машинном обучении (точнее, в выборе функций). Я хотел бы обсудить и другие способы, но я думаю, что это уже было рассмотрено другими стековыми потоками. Надеюсь, что это было полезно!

Карим Джейроуди
источник
2

Вы можете использовать pandas.DataFrame.filterметод для фильтрации или изменения порядка столбцов следующим образом:

df1 = df.filter(['a', 'b'])
Рамин Меликов
источник
0
df[['a','b']] # select all rows of 'a' and 'b'column 
df.loc[0:10, ['a','b']] # index 0 to 10 select column 'a' and 'b'
df.loc[0:10, ['a':'b']] # index 0 to 10 select column 'a' to 'b'
df.iloc[0:10, 3:5] # index 0 to 10 and column 3 to 5
df.iloc[3, 3:5] # index 3 of column 3 to 5
Биплоб Дас
источник