panda loc vs iloc vs ix vs at vs iat?

171

Baru-baru ini mulai bercabang dari tempat aman saya (R) ke Python dan dan saya agak bingung dengan lokalisasi sel / seleksi di Pandas. Saya telah membaca dokumentasinya tetapi saya berjuang untuk memahami implikasi praktis dari berbagai pilihan pelokalan / pemilihan.

  • Apakah ada alasan mengapa saya harus menggunakan .locatau menggunakan .ilocopsi yang paling umum .ix?
  • Saya mengerti bahwa .loc, iloc, at, dan iatdapat memberikan beberapa dijamin kebenaran yang .ixtidak dapat menawarkan, tapi saya juga membaca di mana .ixcenderung menjadi solusi tercepat di seluruh papan.
  • Tolong jelaskan alasan di dunia nyata, praktik terbaik di balik menggunakan apa pun selain .ix?
coretan
sumber
3
locadalah pengindeksan berbasis label sehingga pada dasarnya mencari nilai dalam satu baris, ilocadalah pengindeksan berbasis baris integer, ixadalah metode umum yang pertama kali melakukan berbasis label, jika gagal maka jatuh ke basis integer. atsudah usang dan disarankan Anda tidak menggunakannya lagi. Hal lain yang perlu dipertimbangkan adalah apa yang Anda coba lakukan karena beberapa metode ini memungkinkan pengirisan, dan penugasan kolom, sejujurnya, dokumennya
EdChum
1
@ EdChum - apa yang membuat Anda mengatakan itu atsudah usang? Saya tidak melihatnya di dokumen at (atau iat ).
Russ
1
Itu kesalahan itu tidak ditinggalkan, saya pikir ada beberapa pembicaraan tentang penghentian tetapi ide ini dibatalkan karena saya pikir itu lebih cepat
EdChum
4
Penjelasan detail antara loc, ixdan di ilocsini: stackoverflow.com/questions/31593201/…
Alex Riley

Jawaban:

142

loc: hanya bekerja pada indeks
iloc: bekerja pada posisi
ix: Anda bisa mendapatkan data dari dataframe tanpa harus di indeks
di: dapatkan nilai skalar. Ini adalah loc
iat yang sangat cepat : Dapatkan nilai skalar. Ini iloc yang sangat cepat

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

Catatan: Sampai pandas 0.20.0, yang .ixpengindeks yang ditinggalkan mendukung lebih ketat .ilocdan .locpengindeks.

lautremont
sumber
9
Jika atdan iatmerupakan versi yang sangat cepat locdan iloc, lalu mengapa menggunakan locdan ilocsama sekali?
Ray
57
atdan iatdimaksudkan untuk mengakses skalar, yaitu elemen tunggal dalam kerangka data, sementara locdan ilocsedang mengakses beberapa elemen pada saat yang sama, berpotensi untuk melakukan operasi vektor.
ncasas
@ncasas - jika saya membaca dokumentasi dengan benar. hanya dapat mengakses dengan indeks sementara .loc juga dapat mengakses dengan nama kolom. Apakah ada cara untuk menggunakan .at yang lebih cepat tetapi menggunakan nama kolom alih-alih indeks? Seperti mengganti x = df.loc [df.Id == source_Id, 'someValue'] .nilai [0] dengan x = df.at [df.Id == source_Id, 'someValue']. Versi dengan .at melempar "ValueError: Pada pengindeksan berdasarkan pada indeks integer hanya dapat memiliki pengindeks integer"
Vega
94

Diperbarui untuk pandas 0.20diberikan yang ixsudah usang. Ini menunjukkan tidak hanya bagaimana menggunakan loc, iloc, at, iat, set_value, tapi bagaimana untuk mencapai, campuran pengindeksan berdasarkan posisi / label.


loc- berbasis label
Memungkinkan Anda untuk melewatkan array 1-D sebagai pengindeks. Array dapat berupa irisan (himpunan bagian) dari indeks atau kolom, atau mereka bisa menjadi array boolean yang panjangnya sama dengan indeks atau kolom.

Catatan Khusus: ketika pengindeks skalar dilewatkan, locdapat menetapkan nilai indeks atau kolom baru yang tidak ada sebelumnya.

# 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- Posisi berdasarkan
Mirip dengan lockecuali dengan posisi bukan nilai indeks. Namun, Anda tidak dapat menetapkan kolom atau indeks baru.

# 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- Pekerjaan berbasis label
sangat mirip dengan locuntuk pengindeks skalar. Tidak dapat beroperasi pada pengindeks array. Bisa! menetapkan indeks dan kolom baru.

Keuntungan lebih dari locini adalah bahwa ini lebih cepat.
Kerugiannya adalah Anda tidak dapat menggunakan array untuk pengindeks.

# 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- Pekerjaan berbasis posisi
mirip dengan iloc. Tidak dapat bekerja di pengindeks array. Tidak bisa! menetapkan indeks dan kolom baru.

Keuntungan lebih dari ilocini adalah bahwa ini lebih cepat.
Kerugiannya adalah Anda tidak dapat menggunakan array untuk pengindeks.

# 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- Pekerjaan berbasis label
sangat mirip dengan locuntuk pengindeks skalar. Tidak dapat beroperasi pada pengindeks array. Bisa! menetapkan indeks dan kolom baru

Keuntungan Super cepat, karena ada sedikit overhead!
Kerugian Ada sedikit overhead karena pandastidak melakukan banyak pemeriksaan keamanan. Gunakan dengan risiko Anda sendiri . Juga, ini tidak dimaksudkan untuk penggunaan umum.

# 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_valuedengantakable=True - posisi berdasarkan
Pekerjaan mirip denganiloc. Tidak dapat bekerja di pengindeks array. Tidak bisa! menetapkan indeks dan kolom baru.

Keuntungan Super cepat, karena ada sedikit overhead!
Kerugian Ada sedikit overhead karena pandastidak melakukan banyak pemeriksaan keamanan. Gunakan dengan risiko Anda sendiri . Juga, ini tidak dimaksudkan untuk penggunaan umum.

# 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)
piRquared
sumber
Jadi, apakah ada cara sederhana untuk membaca / mengatur beberapa kolom berdasarkan posisi? Lebih jauh, katakanlah, saya ingin menambahkan array nilai masing-masing ke dalam kolom baru, apakah ini mudah dilakukan?
wordsmith
@wordsmith ada beberapa cara mudah untuk menambahkan kolom baru ke akhir bingkai data. Atau bahkan awal. Jika posisi terlibat maka tidak, tidak ada cara mudah.
piRSquared
Jawaban ini adalah apa yang saya butuhkan! Panda memang kuat, tapi itu dengan mengorbankan membuat segalanya sangat rumit untuk dipahami dan disatukan.
slhck
1
Catatan yang set_valuetelah ditinggalkan mendukung .atdan .iatsejak versi 0.21
nedned
59

Ada dua cara utama panda menentukan pilihan dari DataFrame.

  • Dengan Label
  • Menurut Lokasi Integer

Dokumentasi menggunakan istilah posisi untuk merujuk ke lokasi integer . Saya tidak suka terminologi ini karena saya merasa itu membingungkan. Lokasi integer lebih deskriptif dan tepat untuk apa .iloc. Kata kuncinya di sini adalah INTEGER - Anda harus menggunakan bilangan bulat saat memilih berdasarkan lokasi bilangan bulat.

Sebelum menampilkan ringkasan, mari kita semua memastikan bahwa ...

.ix sudah usang dan ambigu dan tidak boleh digunakan

Ada tiga pengindeks utama untuk panda. Kami memiliki operator pengindeksan itu sendiri (kurung []) .loc,, dan .iloc. Mari kita simpulkan mereka:

  • []- Terutama memilih himpunan bagian kolom, tetapi dapat memilih baris juga. Tidak dapat secara bersamaan memilih baris dan kolom.
  • .loc - memilih himpunan bagian baris dan kolom dengan label saja
  • .iloc - memilih himpunan bagian baris dan kolom dengan lokasi integer saja

Saya hampir tidak pernah menggunakan .atatau .iatkarena mereka tidak menambahkan fungsionalitas tambahan dan hanya dengan sedikit peningkatan kinerja. Saya akan melarang penggunaannya kecuali jika Anda memiliki aplikasi yang sangat sensitif waktu. Apapun, kami memiliki ringkasannya:

  • .at memilih nilai skalar tunggal dalam DataFrame hanya dengan label
  • .iat memilih nilai skalar tunggal dalam DataFrame hanya dengan lokasi integer

Selain pemilihan berdasarkan label dan lokasi integer, pemilihan boolean juga dikenal sebagai pengindeksan boolean .


Contoh menjelaskan .loc,, .ilocseleksi boolean dan .atdan .iatditunjukkan di bawah ini

Kami pertama-tama akan fokus pada perbedaan antara .locdan .iloc. Sebelum kita berbicara tentang perbedaan, penting untuk memahami bahwa DataFrames memiliki label yang membantu mengidentifikasi setiap kolom dan setiap baris. Mari kita lihat contoh 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'])

masukkan deskripsi gambar di sini

Semua kata dalam huruf tebal adalah label. Label, age, color, food, height, scoredan statedigunakan untuk kolom . Label lain, Jane, Nick, Aaron, Penelope, Dean, Christina, Corneliadigunakan sebagai label untuk baris. Secara kolektif, label baris ini dikenal sebagai indeks .


Cara utama untuk memilih baris tertentu dalam DataFrame adalah dengan .locdan .ilocpengindeks. Masing-masing pengindeks ini juga dapat digunakan untuk secara bersamaan memilih kolom tetapi lebih mudah untuk hanya fokus pada baris untuk saat ini. Juga, masing-masing pengindeks menggunakan seperangkat tanda kurung yang segera mengikuti nama mereka untuk membuat pilihan mereka.

.loc memilih data hanya dengan label

Pertama-tama kita akan berbicara tentang .locpengindeks yang hanya memilih data dengan indeks atau label kolom. Dalam DataFrame sampel kami, kami telah memberikan nama yang berarti sebagai nilai untuk indeks. Banyak DataFrames tidak akan memiliki nama yang berarti dan sebaliknya, default ke hanya bilangan bulat dari 0 hingga n-1, di mana n adalah panjang (jumlah baris) dari DataFrame.

Ada banyak input berbeda yang dapat Anda gunakan untuk .loctiga dari mereka

  • Sebuah benang
  • Daftar string
  • Notasi irisan menggunakan string sebagai nilai awal dan berhenti

Memilih satu baris dengan .loc dengan sebuah string

Untuk memilih satu baris data, letakkan label indeks di dalam tanda kurung berikut .loc.

df.loc['Penelope']

Ini mengembalikan baris data sebagai Seri

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

Memilih beberapa baris dengan .loc dengan daftar string

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

Ini mengembalikan DataFrame dengan baris dalam urutan yang ditentukan dalam daftar:

masukkan deskripsi gambar di sini

Memilih beberapa baris dengan .loc dengan notasi slice

Notasi irisan didefinisikan oleh nilai awal, berhenti dan langkah. Saat mengiris dengan label, panda menyertakan nilai stop dalam pengembalian. Berikut irisan dari Harun ke Dean, inklusif. Ukuran langkahnya tidak ditentukan secara eksplisit tetapi default ke 1.

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

masukkan deskripsi gambar di sini

Irisan kompleks dapat diambil dengan cara yang sama seperti daftar Python.

.iloc memilih data hanya dengan lokasi integer

Sekarang mari kita beralih ke .iloc. Setiap baris dan kolom data dalam DataFrame memiliki lokasi integer yang mendefinisikannya. Ini merupakan tambahan untuk label yang ditampilkan secara visual dalam output. Lokasi integer hanyalah jumlah baris / kolom dari atas / kiri mulai dari 0.

Ada banyak input berbeda yang dapat Anda gunakan untuk .iloctiga dari mereka

  • Bilangan bulat
  • Daftar bilangan bulat
  • Notasi irisan menggunakan bilangan bulat sebagai nilai awal dan berhenti

Memilih satu baris dengan .iloc dengan integer

df.iloc[4]

Ini mengembalikan baris ke-5 (lokasi integer 4) sebagai Seri

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

Memilih beberapa baris dengan .iloc dengan daftar bilangan bulat

df.iloc[[2, -2]]

Ini mengembalikan DataFrame dari baris ketiga dan kedua ke terakhir:

masukkan deskripsi gambar di sini

Memilih beberapa baris dengan .iloc dengan notasi slice

df.iloc[:5:3]

masukkan deskripsi gambar di sini


Pemilihan baris dan kolom secara simultan dengan .loc dan .iloc

Satu kemampuan luar biasa dari keduanya .loc/.ilocadalah kemampuan mereka untuk memilih baris dan kolom secara bersamaan. Dalam contoh di atas, semua kolom dikembalikan dari setiap pilihan. Kita dapat memilih kolom dengan tipe input yang sama seperti yang kita lakukan untuk baris. Kita hanya perlu memisahkan pemilihan baris dan kolom dengan koma .

Misalnya, kita dapat memilih baris Jane, dan Dean hanya dengan tinggi kolom, skor, dan status seperti ini:

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

masukkan deskripsi gambar di sini

Ini menggunakan daftar label untuk baris dan notasi irisan untuk kolom

Kami secara alami dapat melakukan operasi serupa dengan .ilochanya menggunakan bilangan bulat.

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

Pilihan serentak dengan label dan lokasi integer

.ixdigunakan untuk membuat pilihan secara bersamaan dengan label dan lokasi integer yang berguna tetapi membingungkan dan ambigu pada waktu dan untungnya itu sudah usang. Jika Anda perlu membuat pilihan dengan campuran label dan lokasi integer, Anda harus membuat label pilihan atau lokasi integer Anda.

Misalnya, jika kita ingin memilih baris Nickdan Corneliabersama dengan kolom 2 dan 4, kita bisa menggunakan .locdengan mengubah bilangan bulat menjadi label dengan yang berikut ini:

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

Atau sebagai alternatif, ubah label indeks menjadi bilangan bulat dengan get_locmetode indeks.

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

Seleksi Boolean

Pengindeks .loc juga dapat melakukan seleksi boolean. Misalnya, jika kita tertarik untuk menemukan semua baris di mana usia di atas 30 dan mengembalikan hanya kolom fooddan scorekita dapat melakukan hal berikut:

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

Anda dapat meniru ini dengan .iloctetapi Anda tidak bisa mengirimkannya seri boolean. Anda harus mengubah Seri boolean menjadi array numpy seperti ini:

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

Memilih semua baris

Dimungkinkan untuk digunakan .loc/.ilochanya untuk pemilihan kolom. Anda dapat memilih semua baris dengan menggunakan titik dua seperti ini:

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

masukkan deskripsi gambar di sini


Operator pengindeksan [],, dapat mengiris dapat memilih baris dan kolom juga tetapi tidak secara bersamaan.

Kebanyakan orang akrab dengan tujuan utama operator pengindeksan DataFrame, yaitu untuk memilih kolom. Sebuah string memilih kolom tunggal sebagai Seri dan daftar string memilih beberapa kolom sebagai DataFrame.

df['food']

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

Menggunakan daftar memilih banyak kolom

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

masukkan deskripsi gambar di sini

Apa yang kurang dikenal orang adalah, ketika notasi slice digunakan, maka seleksi terjadi oleh label baris atau dengan lokasi integer. Ini sangat membingungkan dan sesuatu yang hampir tidak pernah saya gunakan tetapi berhasil.

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

masukkan deskripsi gambar di sini

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

masukkan deskripsi gambar di sini

Ketertarikan .loc/.ilocuntuk memilih baris sangat disukai. Operator pengindeksan saja tidak dapat memilih baris dan kolom secara bersamaan.

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

Seleksi oleh .atdan.iat

Seleksi dengan .athampir identik dengan .loctetapi hanya memilih satu 'sel' di DataFrame Anda. Kami biasanya menyebut sel ini sebagai nilai skalar. Untuk menggunakannya .at, berikan label baris dan kolom yang dipisahkan dengan koma.

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

Seleksi dengan .iathampir identik dengan .iloctetapi hanya memilih nilai skalar tunggal. Anda harus memberikan bilangan bulat untuk lokasi baris dan kolom

df.iat[2, 5]
'FL'
Ted Petrou
sumber
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
Lidia
sumber
4

Mari kita mulai dengan df kecil ini:

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

Kami akan melakukannya

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

Dengan ini kami memiliki:

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

Jadi kita tidak bisa menggunakan .iat untuk subset, di mana kita harus menggunakan .iloc saja.

Tapi mari kita coba keduanya untuk memilih dari df yang lebih besar dan mari kita periksa kecepatan ...

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

Jadi dengan .loc kita dapat mengatur subset dan dengan .at hanya satu skalar, tetapi .at lebih cepat dari .loc

:-)

Fabio Pomi
sumber