Вибір декількох стовпців у фреймі даних панди


1109

У мене є дані в різних стовпцях, але я не знаю, як їх витягти, щоб зберегти їх в іншій змінній.

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

Як вибрати 'a', 'b'і зберегти його , щоб df1?

я намагався

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

Жоден, здається, не працює.


2
Ніколи не хочеш використовувати, .ixяк це неоднозначно. Використовуйте .ilocабо .locякщо потрібно.
Акумен

1
Чи є спосіб це зробити, не посилаючись на назви заголовків? як і в R, я можу це зробити так: > csvtable_imp_1 <- csvtable_imp[0:6]і він вибирає кількість дельти перших стовпців між 0 і 6. Все, що мені потрібно було зробити, - це прочитати таблицю csv як розмежувану з lib readr.
MichaelR

Я трохи більше працював з цим. Знайшов щось, що працювало так, як хотілося. За замовчуванням - вибір номерів знаків, а не стовпців. infile_1 = largefile_stay.ix[:,0:6]
MichaelR

3
Для тих, хто спіткнувся з цим запізненням, ixтепер застаріло. Pandas рекомендує використовувати або: loc(індексацію на основі міток), або iloc(індексацію на основі позиції).
ЗайдХ

Відповіді:


1768

Імена стовпців (які є рядками) не можна нарізати так, як ви намагалися.

Тут у вас є пара варіантів. Якщо з контексту ви знаєте, які змінні потрібно вирізати, ви можете просто повернути перегляд лише цих стовпців, передавши список у __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методу об'єкта фрейму даних для отримання індексів стовпців.

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

Тепер ви можете використовувати цей словник для доступу до стовпців через імена та використання iloc.


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'))return 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-му та четвертому стовпцях. Якщо ви не знаєте їх імен під час запуску сценарію, ви можете це зробити

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

Як вказує EMS у своїй відповіді , df.ixфрагменти стовпців дещо стисліші, але .columnsінтерфейс нарізки може бути більш природним, оскільки він використовує синтаксис індексації / нарізки списку ванільного 1-D пітону.

ПОПЕРЕДЖЕННЯ: невірне 'index'ім’я для DataFrameстовпця Ця ж мітка використовується і для реального df.indexатрибута, Indexмасиву. Таким чином, ваш стовпець повертається, df['index']а реальний індекс DataFrame повертається df.index. 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]помиляєтесь. І використання стандартних позначень нарізки пітона для створення послідовності / серії не вводить в оману IMO. Але мені подобається ваш обхід інтерфейсу DataFrame для доступу до базового масиву numpy ix.
варильні панелі

Ви маєте рацію в цьому випадку, але я намагався зробити те, що загалом, нарізка з мітками в Pandas включає в себе кінцеву точку зрізу (або, принаймні, така поведінка в більшості попередніх версій Pandas). Отже, якщо ви отримаєте df.columnsі хочете нарізати його за міткою , то ви матимете іншу семантику зрізів, ніж якби ви розрізали її за цілою позицією індексу . Я, безумовно, не пояснив це добре в своєму попередньому коментарі.
Ely

Ааа, тепер я бачу вашу думку. Я забув, що columnsце непорушна серія, і геттер перестала використовувати етикетки як індекси. Дякуємо, що знайшли час для уточнення.
варильні панелі

2
Зверніть увагу на попередження про депрекацію: .ix застаріло. Тому це має сенс: newdf = df [df.column [2: 4]]
Martien Lubberink

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?
куанб

5
df[['b', 'c']].rename(columns = {'b' : 'foo', 'c' : 'bar'})
Грег

61

Я усвідомлюю, що це питання досить старе, але в останній версії панди є простий спосіб зробити саме це. Назви стовпців (які є рядками) можна нарізати будь-яким способом.

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

6
Це можна зробити лише при створенні. Питання полягає в тому, чи є він у вас вже у фреймі даних.
Banjocat

2
@Banjocat, він працює з існуючим фреймом даних
mhery

23

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

Просто кажу

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

поверне DataFrame із лише стовпцями bтаc .

dropМетод документований тут .


23

З пандами,

назви стовпців дотепності

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

вибрати по iloc та конкретні стовпці з номером індексу:

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

з локальними іменами стовпців можна використовувати як

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]працювало б до тих пір, поки було знайдено принаймні 1 ключ (інакше він підніме a KeyError). Така поведінка застаріла і тепер відображає попереджувальне повідомлення. Рекомендована альтернатива - використання.reindex() .

Детальніше читайте на сторінці Індексація та Вибір даних


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

8

Якщо ви хочете отримати один елемент за індексом рядків та назвою стовпців, ви можете це зробити так само df['b'][0] . Це так просто, як ви можете уявити.

Або ви можете використовувати df.ix[0,'b']змішане використання індексу та мітки.

Примітка: оскільки v0.20 ixзастаріло на користь loc/ iloc.


6

Один різний і простий підхід: повторення рядків

використовуючи iterow

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

5
Не рекомендуйте використовувати iterrow (). Це кричущий фактор найгіршого антидіаграму за всю історію панд.
cs95

Не могли б ви пояснити, що ви маєте на увазі під "найгіршим анти-шаблоном"?
Анкіта

1
IMHO, iterrow () має бути останнім варіантом при використанні панд.
Ельф

5

Різні підходи, обговорені у вищезазначених відповідях, ґрунтуються на припущенні, що або користувач знає індекси стовпців, які потрібно скинути або підмножити, або користувач бажає підмножити кадр даних, використовуючи діапазон стовпців (наприклад, між "C": "E") . pandas.DataFrame.drop () , безумовно, є можливим підмножити дані на основі списку стовпців, визначених користувачем (хоча ви повинні бути обережними, що ви завжди використовуєте копію фрейму даних, а параметри inplace не повинні встановлювати значення True !!)

Інший варіант полягає у використанні pandas.column.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


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

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

У мене є такий список / 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.