pandas loc vs. iloc vs. ix vs. at at iat?


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

1
Це помилка, вона не застаріла, я думаю, що говорили про її
зняття,

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, але використовувати ім'я стовпця замість індексу? Як і заміни x = df.loc [df.Id == source_Id, 'someValue']. ​​Значення [0] на x = df.at [df.Id == source_Id, 'someValue']. Версія з .at кидає "ValueError: За індексуванням на цілому індексі можуть мати лише цілі індекси"
Вега

94

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


loc- на основі міток
Дозволяє передавати 1-D масиви як індексатори. Масиви можуть бути або фрагментами (підмножинами) індексу, або стовпчиком, або вони можуть бути булевими масивами, що за довжиною дорівнює індексу або стовпцям.

Спеціальна примітка: коли передається скалярний індексатор, 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скалярні індекси. Неможливо працювати з індексаторами масиву. Можна! призначити нові індекси та стовпці

Перевага Супер швидкий, адже накладних витрат дуже мало!
Недоліки Накладних витрат дуже мало, тому що 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. Неможливо працювати в індексаторах масивів. Не можу! призначити нові індекси та стовпці.

Перевага Супер швидкий, адже накладних витрат дуже мало!
Недоліки Накладних витрат дуже мало, тому що 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)

Отже, чи існує простий спосіб читання / встановлення декількох стовпців за позицією? Далі, скажімо, я хотів додати масив значень кожен до нових стовпців, це легко зробити?
wordmith

@wordsmith є прості способи додавання нових стовпців до кінця фрейму даних. Або навіть початок. Якщо позиції задіяні, то ні, це непростий спосіб.
piRSquared

Ця відповідь була саме тим, що мені потрібно! Панди, безумовно, потужні, але це пов'язано з тим, щоб зробити все надзвичайно складним для розуміння та складання разом.
slhck

1
Зауважимо, що set_valueце застаріле на користь .atта .iatз версії 0.21
неділю

59

Є два основні способи, завдяки яким панди здійснюють вибір з DataFrame.

  • За міткою
  • За цілим розташуванням

У документації використовується термін позиція для позначення цілого місця розташування . Мені не подобається ця термінологія, оскільки я вважаю це заплутаною. Розташування цілого числа є більш описовим і саме те, що .ilocозначає. Ключове слово тут - INTEGER - ви повинні використовувати цілі числа при виборі за цілим розташуванням.

Перш ніж показати резюме, давайте всі переконайтесь, що ...

.ix застарілий і неоднозначний, і його ніколи не слід використовувати

Для панд є три первинні індексатори . У нас є сам оператор індексації (дужки []) .loc, та .iloc. Підведемо їх підсумки:

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

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

  • .at вибирає одне скалярне значення у DataFrame лише за міткою
  • .iat вибирає одне скалярне значення в DataFrame лише за цілим розташуванням

Окрім вибору за міткою та цілим розташуванням, існує булева вибір, також відома як булева індексація .


Приклади, що пояснюють .loc, .ilocбулевий вибір та .atі .iatнаведені нижче

Спершу зупинимось на відмінностях між .locта .iloc. Перш ніж говорити про відмінності, важливо розуміти, що DataFrames мають мітки, які допомагають ідентифікувати кожен стовпець та кожен рядок. Давайте подивимось на зразок 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 із позначенням фрагмента

Позначення зрізів визначаються значеннями початку, зупинки та кроку. Під час нарізки за міткою панди включають значення зупинки у зворотному порядку. Наступні фрагменти від Аарона до Діна, включно. Її розмір кроку не визначено прямо, але за замовчуванням дорівнює 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є їх здатність одночасно обирати і рядки, і стовпці. У наведених вище прикладах усі стовпці поверталися з кожного вибору. Ми можемо вибирати стовпці з тими ж типами входів, що і для рядків. Нам просто потрібно відокремити виділення рядків і стовпців комою .

Наприклад, ми можемо вибрати рядки Jane та Dean із лише висотою стовпців, оцінкою та станом так:

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методом індексу.

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.