панды лок против илок против икс против у против иат?


171

Недавно начал переходить из моего безопасного места (R) в Python, и меня немного смущает локализация / выборка ячеек в Pandas. Я прочитал документацию, но изо всех сил пытаюсь понять практические последствия различных вариантов локализации / выбора.

  • Есть ли причина , почему я никогда не должен использовать .locили .ilocпо наиболее общем вариант .ix?
  • Я понимаю , что .loc, iloc, at, и iatможет обеспечить определенную гарантию правильности , что .ixне может предложить, но я также читал, как .ixправило, является самым быстрым решением по всем направлениям.
  • Пожалуйста, объясните реальную практическую причину использования чего-либо, кроме .ix?


3
locиндексирование на основе меток, поэтому в основном выполняется поиск значения в строке; ilocиндексация на основе целочисленных строк; ixэто общий метод, который вначале выполняет основанную на метках метку, в случае неудачи он переходит к целочисленной. atустарела, и рекомендуется не использовать его больше. Другая вещь, которую следует учитывать, - это то, что вы пытаетесь сделать, так как некоторые из этих методов позволяют нарезать и назначать столбцы, если честно, документы довольно ясны: pandas.pydata.org/pandas-docs/stable/indexing.html
EdChum

1
@EdChum - что заставляет тебя говорить, что atэто устарело? Я не вижу этого в документах at (или iat ).
Расс

1
Это ошибка, которая не считается устаревшей, я думаю, что некоторые говорили о том, что она не рекомендуется, но эта идея была отброшена, потому что я думаю, что это быстрее
EdChum

4
Подробное объяснение между loc, ixи ilocздесь: stackoverflow.com/questions/31593201/...
Alex Riley

Ответы:


142

loc: работать только с индексом
iloc: работать с позицией
ix: Вы можете получать данные из фрейма данных без их нахождения в индексе по
адресу: получить скалярные значения. Это очень быстрое
определение: получить скалярные значения. Это очень быстрый iloc

http://pyciencia.blogspot.com/2015/05/obtener-y-filtrar-datos-de-un-dataframe.html

Примечание. По состоянию pandas 0.20.0на данный момент .ixиндексатор устарел в пользу более строгих .ilocи .locиндексаторов.


9
Если atи iatявляются очень быстрыми версиями locи iloc, то зачем использовать locи ilocвообще?
Рэй

57
atи iatпредназначенный для доступа к скаляру, то есть к единственному элементу в кадре данных, в то же время locи ilocдля доступа к нескольким элементам одновременно, потенциально для выполнения векторизованных операций.
Ncasas

@ncasas - если я правильно читаю документацию, доступ к .at возможен только по индексу, а доступ к .loc - по имени столбца. Есть ли способ использовать более быстрый .at, но использовать имя столбца вместо индекса? Как замена x = df.loc [df.Id == source_Id, 'someValue']. ​​Values ​​[0] на x = df.at [df.Id == source_Id, 'someValue']. Версия с .at выдает «ValueError: При индексировании на основе целочисленного индекса могут быть только целочисленные индексаторы»
Vega

94

Обновлено для pandas 0.20данного, что ixустарело. Это свидетельствует не только то, как использовать loc, iloc, at, iat, set_value, но как добиться, смешанной индексации на основе позиционных / метки.


loc- на основе меток
Позволяет передавать одномерные массивы в качестве индексаторов. Массивы могут быть либо срезами (подмножествами) индекса или столбца, либо они могут быть логическими массивами, длина которых равна индексу или столбцам.

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

# label based, but we can use position values
# to get the labels from the index object
df.loc[df.index[2], 'ColName'] = 3

df.loc[df.index[1:3], 'ColName'] = 3

iloc- на основе позиции
Аналогично тому, locза исключением позиций, а не значений индекса. Однако вы не можете назначать новые столбцы или индексы.

# position based, but we can get the position
# from the columns object via the `get_loc` method
df.iloc[2, df.columns.get_loc('ColName')] = 3

df.iloc[2, 4] = 3

df.iloc[:3, 2:4] = 3

at- этикетка на основе
произведения очень похоже на locскалярные индексатор. Не может работать с индексаторами массива. Жестяная банка! назначить новые индексы и столбцы.

Преимущество в locтом, что это быстрее.
Недостатком является то, что вы не можете использовать массивы для индексаторов.

# label based, but we can use position values
# to get the labels from the index object
df.at[df.index[2], 'ColName'] = 3

df.at['C', 'ColName'] = 3

iat- Позиция на основе
работает аналогично iloc. Не может работать в индексаторах массива. Не может! назначить новые индексы и столбцы.

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

# position based, but we can get the position
# from the columns object via the `get_loc` method
IBM.iat[2, IBM.columns.get_loc('PNL')] = 3

set_value- этикетка на основе
произведения очень похоже на locскалярные индексатор. Не может работать с индексаторами массива. Жестяная банка! назначить новые индексы и столбцы

Преимущество Super fast, потому что накладных расходов очень мало!
Недостаток Очень мало накладных расходов, потому что pandasне выполняется куча проверок безопасности. Используйте на свой страх и риск . Кроме того, это не предназначено для общественного использования.

# label based, but we can use position values
# to get the labels from the index object
df.set_value(df.index[2], 'ColName', 3)

set_valueсtakable=True - позиция на основе
работает аналогичноiloc. Не может работать в индексаторах массива. Не может! назначить новые индексы и столбцы.

Преимущество Super fast, потому что накладных расходов очень мало!
Недостаток Очень мало накладных расходов, потому что pandasне выполняется куча проверок безопасности. Используйте на свой страх и риск . Кроме того, это не предназначено для общественного использования.

# position based, but we can get the position
# from the columns object via the `get_loc` method
df.set_value(2, df.columns.get_loc('ColName'), 3, takable=True)

Итак, есть ли простой способ чтения / установки нескольких столбцов по позиции? Далее, скажем, я хотел добавить массив значений каждый в новые столбцы, это легко сделать?
Wordsmith

@wordsmith есть простые способы добавления новых столбцов в конец кадра данных. Или даже начало. Если позиции задействованы, то нет, простого пути нет.
piRSquared

Этот ответ был именно то, что мне нужно! Панды, безусловно, мощные, но это достигается за счет того, что все очень сложно понять и собрать воедино.
slhck

1
Обратите внимание , что set_valueявляется устаревшим в пользу .atи , .iatначиная с версии 0,21
nedned

59

Есть два основных способа, которыми pandas делает выбор из DataFrame.

  • По метке
  • По целому расположению

В документации термин « позиция» используется для обозначения целочисленного местоположения . Мне не нравится эта терминология, поскольку я чувствую, что она сбивает с толку. Целочисленное расположение более наглядно и является именно тем, что .ilocобозначает. Ключевое слово здесь - INTEGER - вы должны использовать целые числа при выборе по целому расположению.

Прежде чем показывать резюме, давайте убедимся, что ...

.ix устарела и неоднозначна и никогда не должна использоваться

Есть три основных индекса для панд. У нас есть сам оператор индексации (скобки []) .loc, и .iloc. Давайте подведем их итоги:

  • []- В первую очередь выбирает подмножества столбцов, но также может выбирать строки. Невозможно одновременно выбрать строки и столбцы.
  • .loc - выбирает подмножества строк и столбцов только по меткам
  • .iloc - выбирает подмножества строк и столбцов только целочисленным расположением

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

  • .at выбирает одно скалярное значение в DataFrame только по метке
  • .iat выбирает одно скалярное значение в DataFrame только по целочисленному расположению

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


Примеры, поясняющие .loc, .ilocбулево выделение и .atи .iatпоказаны ниже

Сначала мы сосредоточимся на различиях между .locи .iloc. Прежде чем говорить о различиях, важно понять, что в фреймах данных есть метки, которые помогают идентифицировать каждый столбец и каждую строку. Давайте посмотрим на пример DataFrame:

df = pd.DataFrame({'age':[30, 2, 12, 4, 32, 33, 69],
                   'color':['blue', 'green', 'red', 'white', 'gray', 'black', 'red'],
                   'food':['Steak', 'Lamb', 'Mango', 'Apple', 'Cheese', 'Melon', 'Beans'],
                   'height':[165, 70, 120, 80, 180, 172, 150],
                   'score':[4.6, 8.3, 9.0, 3.3, 1.8, 9.5, 2.2],
                   'state':['NY', 'TX', 'FL', 'AL', 'AK', 'TX', 'TX']
                   },
                  index=['Jane', 'Nick', 'Aaron', 'Penelope', 'Dean', 'Christina', 'Cornelia'])

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

Все слова, выделенные жирным шрифтом, являются метками. Этикетки, age, color, food, height, scoreи stateиспользуются для столбцов . Другие этикетки, Jane, Nick, Aaron, Penelope, Dean, Christina, Corneliaиспользуются в качестве меток для строк. В совокупности эти метки строк известны как индекс .


Основные способы выбора конкретных строк в DataFrame являются с .locи .ilocиндексаторами. Каждый из этих индексаторов также можно использовать для одновременного выбора столбцов, но сейчас проще сосредоточиться на строках. Кроме того, каждый из индексаторов использует набор скобок, которые следуют сразу за их именем, чтобы сделать свой выбор.

.loc выбирает данные только по меткам

Сначала поговорим об .locиндексаторе, который выбирает данные только по меткам индекса или столбца. В нашем примере DataFrame мы предоставили значимые имена в качестве значений для индекса. Многие DataFrames не будут иметь каких-либо значимых имен, и вместо этого по умолчанию будут использоваться только целые числа от 0 до n-1, где n - длина (количество строк) DataFrame.

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

  • Строка
  • Список строк
  • Запись среза с использованием строк в качестве начального и конечного значений

Выбор одной строки с помощью .loc со строкой

Чтобы выбрать одну строку данных, поместите метку индекса внутри следующих квадратных скобок .loc.

df.loc['Penelope']

Это возвращает строку данных в виде серии

age           4
color     white
food      Apple
height       80
score       3.3
state        AL
Name: Penelope, dtype: object

Выбор нескольких строк с помощью .loc со списком строк

df.loc[['Cornelia', 'Jane', 'Dean']]

Это возвращает DataFrame со строками в порядке, указанном в списке:

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

Выбор нескольких строк с помощью .loc с обозначением слайса

Обозначение среза определяется значениями start, stop и step. При разрезании по метке pandas включает в себя значение стопа в возврате. Следующие кусочки от Аарона до Дина включительно. Размер шага явно не определен, но по умолчанию равен 1.

df.loc['Aaron':'Dean']

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

Сложные фрагменты могут быть взяты так же, как списки Python.

.iloc выбирает данные только по целому расположению

Давайте теперь обратимся к .iloc. Каждая строка и столбец данных в DataFrame имеет целочисленное расположение, которое определяет его. Это в дополнение к метке, которая визуально отображается в выходных данных. Целочисленное местоположение - это просто число строк / столбцов сверху / слева, начиная с 0.

Есть три различных входа, которые вы можете использовать для .ilocтрех из них:

  • Целое число
  • Список целых чисел
  • Запись среза с использованием целых чисел в качестве начального и конечного значений

Выбор одной строки с .iloc с целым числом

df.iloc[4]

Это возвращает 5-ую строку (целочисленное расположение 4) как серию

age           32
color       gray
food      Cheese
height       180
score        1.8
state         AK
Name: Dean, dtype: object

Выбор нескольких строк с .iloc со списком целых чисел

df.iloc[[2, -2]]

Это возвращает DataFrame третьей и второй до последней строки:

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

Выбор нескольких строк с .iloc с обозначением среза

df.iloc[:5:3]

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


Одновременный выбор строк и столбцов с .loc и .iloc

Одной из отличных способностей обоих .loc/.ilocявляется их способность выбирать строки и столбцы одновременно. В приведенных выше примерах все столбцы возвращались из каждого выбора. Мы можем выбрать столбцы с теми же типами ввода, что и для строк. Нам просто нужно разделить выбор строки и столбца запятой .

Например, мы можем выбрать строки Джейн и Дина только с высотой, счетом и состоянием столбцов следующим образом:

df.loc[['Jane', 'Dean'], 'height':]

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

При этом используется список меток для строк и нотации для столбцов

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

df.iloc[[1,4], 2]
Nick      Lamb
Dean    Cheese
Name: food, dtype: object

Одновременный выбор с метками и целочисленным расположением

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

Например, если мы хотим выбрать строки Nickи Corneliaвместе со столбцами 2 и 4, мы могли бы использовать .locпреобразование целых чисел в метки со следующим:

col_names = df.columns[[2, 4]]
df.loc[['Nick', 'Cornelia'], col_names] 

Или, в качестве альтернативы, преобразуйте метки индекса в целые числа с помощью get_locметода index.

labels = ['Nick', 'Cornelia']
index_ints = [df.index.get_loc(label) for label in labels]
df.iloc[index_ints, [2, 4]]

Логическое выделение

Индексатор .loc также может выполнять логический выбор. Например, если мы заинтересованы в том, найти все строки , в которых возраст выше 30 и возвращать только foodи scoreстолбцы , мы можем сделать следующее:

df.loc[df['age'] > 30, ['food', 'score']] 

Вы можете повторить это с, .ilocно вы не можете передать это логический ряд. Вы должны преобразовать логическую серию в массив numpy следующим образом:

df.iloc[(df['age'] > 30).values, [2, 4]] 

Выбор всех строк

Можно использовать .loc/.ilocтолько для выбора столбца. Вы можете выбрать все строки, используя двоеточие, как это:

df.loc[:, 'color':'score':2]

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


Оператор индексации [], может нарезать и может выбирать строки и столбцы тоже, но не одновременно.

Большинству людей знакомо основное назначение оператора индексации DataFrame - выбор столбцов. Строка выбирает один столбец в качестве Серии, а список строк выбирает несколько столбцов в качестве DataFrame.

df['food']

Jane          Steak
Nick           Lamb
Aaron         Mango
Penelope      Apple
Dean         Cheese
Christina     Melon
Cornelia      Beans
Name: food, dtype: object

Использование списка выбирает несколько столбцов

df[['food', 'score']]

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

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

df['Penelope':'Christina'] # slice rows by label

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

df[2:6:2] # slice rows by integer location

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

Явность .loc/.ilocвыбора строк очень предпочтительна. Один оператор индексирования не может одновременно выбирать строки и столбцы.

df[3:5, 'color']
TypeError: unhashable type: 'slice'

Выбор по .atи.iat

Выбор с .atпочти идентичен, .locно он выбирает только одну «ячейку» в вашем DataFrame. Мы обычно называем эту ячейку скалярным значением. Чтобы использовать .at, передайте и метку строки и столбца через запятую.

df.at['Christina', 'color']
'black'

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

df.iat[2, 5]
'FL'

31
df = pd.DataFrame({'A':['a', 'b', 'c'], 'B':[54, 67, 89]}, index=[100, 200, 300])

df

                        A   B
                100     a   54
                200     b   67
                300     c   89
In [19]:    
df.loc[100]

Out[19]:
A     a
B    54
Name: 100, dtype: object

In [20]:    
df.iloc[0]

Out[20]:
A     a
B    54
Name: 100, dtype: object

In [24]:    
df2 = df.set_index([df.index,'A'])
df2

Out[24]:
        B
    A   
100 a   54
200 b   67
300 c   89

In [25]:    
df2.ix[100, 'a']

Out[25]:    
B    54
Name: (100, a), dtype: int64

4

Давайте начнем с этого небольшого df:

import pandas as pd
import time as tm
import numpy as np
n=10
a=np.arange(0,n**2)
df=pd.DataFrame(a.reshape(n,n))

У нас так будет

df
Out[25]: 
        0   1   2   3   4   5   6   7   8   9
    0   0   1   2   3   4   5   6   7   8   9
    1  10  11  12  13  14  15  16  17  18  19
    2  20  21  22  23  24  25  26  27  28  29
    3  30  31  32  33  34  35  36  37  38  39
    4  40  41  42  43  44  45  46  47  48  49
    5  50  51  52  53  54  55  56  57  58  59
    6  60  61  62  63  64  65  66  67  68  69
    7  70  71  72  73  74  75  76  77  78  79
    8  80  81  82  83  84  85  86  87  88  89
    9  90  91  92  93  94  95  96  97  98  99

С этим мы имеем:

df.iloc[3,3]
Out[33]: 33

df.iat[3,3]
Out[34]: 33

df.iloc[:3,:3]
Out[35]: 
    0   1   2   3
0   0   1   2   3
1  10  11  12  13
2  20  21  22  23
3  30  31  32  33



df.iat[:3,:3]
Traceback (most recent call last):
   ... omissis ...
ValueError: At based indexing on an integer index can only have integer indexers

Таким образом, мы не можем использовать .iat для подмножества, где мы должны использовать только .iloc.

Но давайте попробуем оба выбрать больший df и проверим скорость ...

# -*- coding: utf-8 -*-
"""
Created on Wed Feb  7 09:58:39 2018

@author: Fabio Pomi
"""

import pandas as pd
import time as tm
import numpy as np
n=1000
a=np.arange(0,n**2)
df=pd.DataFrame(a.reshape(n,n))
t1=tm.time()
for j in df.index:
    for i in df.columns:
        a=df.iloc[j,i]
t2=tm.time()
for j in df.index:
    for i in df.columns:
        a=df.iat[j,i]
t3=tm.time()
loc=t2-t1
at=t3-t2
prc = loc/at *100
print('\nloc:%f at:%f prc:%f' %(loc,at,prc))

loc:10.485600 at:7.395423 prc:141.784987

Таким образом, с помощью .loc мы можем управлять подмножествами, а с помощью .at - только одним скаляром, но .at быстрее, чем .loc.

:-)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.