gấu trúc loc vs iloc vs ix vs. at vs iat?


171

Gần đây đã bắt đầu phân nhánh từ nơi an toàn (R) của tôi vào Python và hơi bối rối bởi việc chọn / định vị ô trong Pandas. Tôi đã đọc tài liệu nhưng tôi đang cố gắng để hiểu ý nghĩa thực tế của các tùy chọn nội địa hóa / lựa chọn khác nhau.

  • Có một lý do tại sao tôi nên sử dụng .lochoặc .ilocqua tùy chọn chung nhất .ix?
  • Tôi hiểu rằng .loc, iloc, at, và iatcó thể cung cấp một số tính đúng đắn đảm bảo rằng .ixkhông thể cung cấp, nhưng tôi cũng đã đọc ở đâu .ixcó xu hướng là giải pháp nhanh nhất trên bảng.
  • Hãy giải thích lý do thực tế, thực tiễn tốt nhất đằng sau việc sử dụng bất cứ điều gì khác hơn .ix?


2
loclà lập chỉ mục dựa trên nhãn, vì vậy về cơ bản tìm kiếm một giá trị trong một hàng, iloclà lập chỉ mục dựa trên hàng nguyên, ixlà một phương pháp chung đầu tiên thực hiện dựa trên nhãn, nếu thất bại thì nó rơi vào dựa trên số nguyên. atkhông được dùng nữa và khuyên bạn không nên sử dụng nó nữa. Một điều khác cần xem xét là những gì bạn đang cố gắng thực hiện vì một số phương pháp này cho phép cắt và gán cột, thành thật mà nói, các tài liệu khá rõ ràng: pandas.pydata.org/pandas-docs/ sóng / index.html
EdChum

1
@EdChum - điều gì khiến bạn nói đó atlà phản đối? Tôi không thấy nó trong các tài liệu tại (hoặc iat ).
Nga

1
Đó là một lỗi không được phản đối, tôi nghĩ đã có một số thảo luận về việc phản đối nó nhưng ý tưởng này đã bị loại bỏ vì tôi nghĩ nó nhanh hơn
EdChum

4
Chú giải chi tiết giữa loc, ixilocở đây: stackoverflow.com/questions/31593201/...
Alex Riley

Câu trả lời:


142

loc: chỉ hoạt động trên chỉ mục
iloc: hoạt động ở vị trí
ix: Bạn có thể lấy dữ liệu từ khung dữ liệu mà không có trong chỉ mục
tại: lấy giá trị vô hướng. Đó là một định vị rất nhanh
: Nhận các giá trị vô hướng. Nó là một iloc rất nhanh

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

Lưu ý: Kể từ khi pandas 0.20.0, người .ixlập chỉ mục không được ủng hộ bởi những người lập chỉ mục .ilocvà nghiêm ngặt hơn .loc.


9
Nếu atiatlà phiên bản rất nhanh của lociloc, thì tại sao lại sử dụng lociloctất cả?
Ray

57
atiatmột phương tiện để truy cập vô hướng, nghĩa là, một phần tử duy nhất trong khung dữ liệu, trong khi lociloclà các phần tử để truy cập một số phần tử cùng một lúc, có khả năng thực hiện các hoạt động được vector hóa.
ncasas

@ncasas - nếu tôi đọc đúng tài liệu .at chỉ có thể truy cập theo chỉ mục trong khi .loc cũng có thể truy cập theo tên cột. Có cách nào để sử dụng .at nhanh hơn nhưng sử dụng tên cột thay vì chỉ mục không? Giống như thay thế x = df.loc [df.Id == source_Id, 'someValue']. ​​Value [0] bằng x = df.at [df.Id == source_Id, 'someValue']. Phiên bản có .at ném "ValueError: Khi lập chỉ mục dựa trên chỉ số nguyên chỉ có thể có bộ chỉ mục số nguyên"
Vega

94

Cập nhật cho pandas 0.20đã ixđược phản đối. Điều này cho thấy không chỉ làm thế nào để sử dụng loc, iloc, at, iat, set_value, nhưng làm thế nào để hoàn thành, trộn vị trí / nhãn dựa lập chỉ mục.


loc- dựa trên nhãn
Cho phép bạn vượt qua các mảng 1-D dưới dạng chỉ mục. Mảng có thể là các lát (tập con) của chỉ mục hoặc cột hoặc chúng có thể là các mảng boolean có độ dài bằng với chỉ mục hoặc các cột.

Lưu ý đặc biệt: khi một bộ chỉ mục vô hướng được thông qua, loccó thể chỉ định một chỉ mục hoặc giá trị cột mới không tồn tại trước đó.

# 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- vị trí dựa
Tương tự như locngoại trừ với các vị trí thay vì giá trị chỉ mục. Tuy nhiên, bạn không thể gán các cột hoặc chỉ mục mới.

# 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- dựa trên nhãn
Hoạt động rất giống với locchỉ mục vô hướng. Không thể hoạt động trên bộ chỉ mục mảng. Có thể! gán các chỉ số và cột mới.

Lợi thế hơn loclà điều này nhanh hơn.
Nhược điểm là bạn không thể sử dụng mảng cho người lập chỉ mục.

# 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- vị trí dựa trên
công trình tương tự như iloc. Không thể làm việc trong bộ chỉ mục mảng. Không thể! gán các chỉ số và cột mới.

Lợi thế hơn iloclà điều này nhanh hơn.
Nhược điểm là bạn không thể sử dụng mảng cho người lập chỉ mục.

# 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- dựa trên nhãn
Hoạt động rất giống với locchỉ mục vô hướng. Không thể hoạt động trên bộ chỉ mục mảng. Có thể! gán các chỉ số và cột mới

Lợi thế siêu nhanh, vì có rất ít chi phí!
Nhược điểm Có rất ít chi phí vì pandaskhông thực hiện một loạt kiểm tra an toàn. Sử dụng có nguy cơ của riêng bạn . Ngoài ra, điều này không dành cho sử dụng công cộng.

# 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_valuevớitakable=True - vị trí dựa trên
công trình tương tự nhưiloc. Không thể làm việc trong bộ chỉ mục mảng. Không thể! gán các chỉ số và cột mới.

Lợi thế siêu nhanh, vì có rất ít chi phí!
Nhược điểm Có rất ít chi phí vì pandaskhông thực hiện một loạt kiểm tra an toàn. Sử dụng có nguy cơ của riêng bạn . Ngoài ra, điều này không dành cho sử dụng công cộng.

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

Vì vậy, có một cách đơn giản để đọc / đặt nhiều cột theo vị trí? Hơn nữa, tôi muốn thêm một mảng các giá trị vào mỗi cột mới, điều này có dễ thực hiện không?
Wordsmith

@wordsmith có nhiều cách dễ dàng để nối các cột mới vào cuối khung dữ liệu. Hoặc thậm chí là sự khởi đầu. Nếu các vị trí có liên quan thì không, đó không phải là một cách dễ dàng.
piRSquared

Câu trả lời này chỉ là những gì tôi cần! Pandas chắc chắn là mạnh mẽ, nhưng điều đó phải trả giá bằng việc làm cho mọi thứ cực kỳ phức tạp để hiểu và ghép lại với nhau.
slhck

1
Lưu ý rằng set_valueđã không được ủng hộ .at.iatkể từ phiên bản 0.21
ghi

59

Có hai cách chính mà gấu trúc đưa ra các lựa chọn từ DataFrame.

  • Theo nhãn
  • Theo vị trí số nguyên

Tài liệu sử dụng vị trí thuật ngữ để chỉ vị trí số nguyên . Tôi không thích thuật ngữ này vì tôi cảm thấy nó khó hiểu. Vị trí số nguyên là mô tả nhiều hơn và chính xác là những gì .ilocđại diện cho. Từ khóa ở đây là INTEGER - bạn phải sử dụng số nguyên khi chọn theo vị trí số nguyên.

Trước khi hiển thị tóm tắt, tất cả hãy chắc chắn rằng ...

.ix không dùng nữa và không rõ ràng và không bao giờ được sử dụng

Có ba người lập chỉ mục chính cho gấu trúc. Chúng ta có chính toán tử lập chỉ mục (dấu ngoặc []) .loc.iloc. Hãy tóm tắt chúng:

  • []- Chủ yếu chọn các tập hợp con của các cột, nhưng cũng có thể chọn các hàng. Không thể đồng thời chọn hàng và cột.
  • .loc - chỉ chọn các tập hợp con của hàng và cột theo nhãn
  • .iloc - chỉ chọn các tập hợp con của các hàng và cột theo vị trí số nguyên

Tôi gần như không bao giờ sử dụng .athoặc .iatvì họ không thêm chức năng bổ sung và chỉ tăng hiệu suất nhỏ. Tôi sẽ không khuyến khích việc sử dụng chúng trừ khi bạn có một ứng dụng rất nhạy cảm với thời gian. Bất kể, chúng tôi có tóm tắt của họ:

  • .at chỉ chọn một giá trị vô hướng trong DataFrame theo nhãn
  • .iat chỉ chọn một giá trị vô hướng trong DataFrame theo vị trí số nguyên

Ngoài lựa chọn theo nhãn và vị trí số nguyên, lựa chọn boolean còn được gọi là lập chỉ mục boolean tồn tại.


Các ví dụ giải thích .loc, .iloclựa chọn boolean .at.iatđược hiển thị bên dưới

Trước tiên chúng tôi sẽ tập trung vào sự khác biệt giữa .loc.iloc. Trước khi chúng ta nói về sự khác biệt, điều quan trọng là phải hiểu rằng DataFrames có nhãn giúp xác định từng cột và từng hàng. Chúng ta hãy xem một DataFrame mẫu:

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

nhập mô tả hình ảnh ở đây

Tất cả các từ in đậm là nhãn. Các nhãn, age, color, food, height, scorestateđược sử dụng cho các cột . Các nhãn khác, Jane, Nick, Aaron, Penelope, Dean, Christina, Corneliađược sử dụng như nhãn cho các hàng. Chung, các nhãn hàng này được gọi là chỉ mục .


Các cách chính để chọn các hàng cụ thể trong DataFrame là với .loc.ilocbộ chỉ mục. Mỗi trong số các bộ chỉ mục này cũng có thể được sử dụng để chọn đồng thời các cột nhưng bây giờ việc tập trung vào các hàng sẽ dễ dàng hơn. Ngoài ra, mỗi người lập chỉ mục sử dụng một bộ dấu ngoặc ngay lập tức theo tên của họ để đưa ra lựa chọn của họ.

.loc chỉ chọn dữ liệu theo nhãn

Trước tiên chúng ta sẽ nói về bộ .locchỉ mục chỉ chọn dữ liệu theo nhãn chỉ mục hoặc cột. Trong DataFrame mẫu của chúng tôi, chúng tôi đã cung cấp các tên có ý nghĩa làm giá trị cho chỉ mục. Nhiều DataFrames sẽ không có bất kỳ tên có ý nghĩa nào và thay vào đó, mặc định chỉ là các số nguyên từ 0 đến n-1, trong đó n là độ dài (số hàng) của DataFrame.

nhiều đầu vào khác nhau mà bạn có thể sử dụng cho .locba trong số đó là

  • Một chuỗi
  • Một danh sách các chuỗi
  • Ký hiệu lát cắt sử dụng chuỗi làm giá trị bắt đầu và dừng

Chọn một hàng đơn với .loc bằng một chuỗi

Để chọn một hàng dữ liệu, đặt nhãn chỉ mục bên trong dấu ngoặc theo sau .loc.

df.loc['Penelope']

Điều này trả về hàng dữ liệu dưới dạng Sê-ri

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

Chọn nhiều hàng với .loc với danh sách các chuỗi

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

Điều này trả về một DataFrame với các hàng theo thứ tự được chỉ định trong danh sách:

nhập mô tả hình ảnh ở đây

Chọn nhiều hàng với .loc với ký hiệu lát

Ký hiệu lát được xác định bởi các giá trị bắt đầu, dừng và bước. Khi cắt theo nhãn, gấu trúc bao gồm giá trị dừng trong lợi nhuận. Các lát sau đây từ Aaron đến Dean, bao gồm. Kích thước bước của nó không được xác định rõ ràng nhưng được mặc định là 1.

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

nhập mô tả hình ảnh ở đây

Các lát phức tạp có thể được thực hiện theo cách tương tự như danh sách Python.

.iloc chỉ chọn dữ liệu theo vị trí số nguyên

Bây giờ chúng ta hãy chuyển sang .iloc. Mỗi hàng và cột dữ liệu trong DataFrame có một vị trí số nguyên xác định nó. Đây là ngoài nhãn được hiển thị trực quan ở đầu ra. Vị trí số nguyên chỉ đơn giản là số lượng hàng / cột từ đầu / bên trái bắt đầu từ 0.

nhiều đầu vào khác nhau mà bạn có thể sử dụng cho .ilocba trong số đó là

  • Một số nguyên
  • Danh sách các số nguyên
  • Ký hiệu lát cắt sử dụng số nguyên làm giá trị bắt đầu và dừng

Chọn một hàng đơn với .iloc có số nguyên

df.iloc[4]

Điều này trả về hàng thứ 5 (vị trí số nguyên 4) dưới dạng Sê-ri

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

Chọn nhiều hàng với .iloc với danh sách các số nguyên

df.iloc[[2, -2]]

Điều này trả về một DataFrame của hàng thứ ba và thứ hai đến hàng cuối cùng:

nhập mô tả hình ảnh ở đây

Chọn nhiều hàng với .iloc với ký hiệu lát

df.iloc[:5:3]

nhập mô tả hình ảnh ở đây


Lựa chọn đồng thời các hàng và cột với .loc và .iloc

Một khả năng tuyệt vời của cả hai .loc/.iloclà khả năng chọn đồng thời cả hai hàng và cột. Trong các ví dụ trên, tất cả các cột được trả về từ mỗi lựa chọn. Chúng ta có thể chọn các cột có cùng loại đầu vào như chúng ta làm cho các hàng. Chúng ta chỉ cần phân tách lựa chọn hàng và cột bằng dấu phẩy .

Ví dụ: chúng ta có thể chọn các hàng Jane và Dean chỉ với chiều cao, điểm số và trạng thái như thế này:

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

nhập mô tả hình ảnh ở đây

Điều này sử dụng một danh sách các nhãn cho các hàng và ký hiệu lát cho các cột

Chúng ta có thể tự nhiên thực hiện các hoạt động tương tự với .ilocchỉ sử dụng số nguyên.

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

Lựa chọn đồng thời với nhãn và vị trí số nguyên

.ixđã được sử dụng để thực hiện các lựa chọn đồng thời với nhãn và vị trí số nguyên rất hữu ích nhưng đôi khi khó hiểu và mơ hồ và rất may nó đã bị phản đối. Trong trường hợp bạn cần thực hiện lựa chọn với hỗn hợp nhãn và vị trí số nguyên, bạn sẽ phải tạo cả nhãn lựa chọn hoặc vị trí số nguyên.

Chẳng hạn, nếu chúng ta muốn chọn các hàng NickCorneliacùng với cột 2 và 4, chúng ta có thể sử dụng .locbằng cách chuyển đổi các số nguyên thành nhãn với các mục sau:

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

Hoặc cách khác, chuyển đổi nhãn chỉ mục thành số nguyên với get_locphương thức chỉ mục.

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

Lựa chọn Boolean

Bộ chỉ mục .loc cũng có thể thực hiện lựa chọn boolean. Chẳng hạn, nếu chúng ta quan tâm đến việc tìm tất cả các hàng có độ tuổi trên 30 và chỉ trả về các cột foodscorechúng ta có thể làm như sau:

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

Bạn có thể sao chép này với .ilocnhưng bạn không thể vượt qua nó một loạt boolean. Bạn phải chuyển đổi Boolean Series thành một mảng numpy như thế này:

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

Chọn tất cả các hàng

Có thể sử dụng .loc/.iloccho chỉ chọn cột. Bạn có thể chọn tất cả các hàng bằng cách sử dụng dấu hai chấm như thế này:

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

nhập mô tả hình ảnh ở đây


Toán tử lập chỉ mục [], có thể cắt cũng có thể chọn các hàng và cột nhưng không đồng thời.

Hầu hết mọi người đều quen thuộc với mục đích chính của toán tử lập chỉ mục DataFrame, đó là chọn các cột. Một chuỗi chọn một cột làm Sê-ri và một danh sách các chuỗi chọn nhiều cột làm DataFrame.

df['food']

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

Sử dụng một danh sách chọn nhiều cột

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

nhập mô tả hình ảnh ở đây

Điều mọi người ít quen thuộc là, khi ký hiệu lát được sử dụng, thì lựa chọn xảy ra theo nhãn hàng hoặc theo vị trí số nguyên. Điều này rất khó hiểu và một cái gì đó mà tôi gần như không bao giờ sử dụng nhưng nó hoạt động.

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

nhập mô tả hình ảnh ở đây

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

nhập mô tả hình ảnh ở đây

Các nhân chứng .loc/.iloccho việc chọn hàng rất được ưa thích. Toán tử lập chỉ mục không thể chọn các hàng và cột đồng thời.

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

Lựa chọn bởi .at.iat

Lựa chọn .atgần giống với .locnhưng nó chỉ chọn một 'ô' duy nhất trong Khung dữ liệu của bạn. Chúng ta thường gọi ô này là giá trị vô hướng. Để sử dụng .at, hãy chuyển nó cả nhãn hàng và cột được phân tách bằng dấu phẩy.

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

Lựa chọn .iatgần giống với .ilocnhưng nó chỉ chọn một giá trị vô hướng duy nhất. Bạn phải truyền cho nó một số nguyên cho cả vị trí hàng và cột

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

Hãy bắt đầu với df nhỏ này:

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

Chúng ta sẽ có

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

Với điều này, chúng tôi có:

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

Vì vậy, chúng ta không thể sử dụng .iat cho tập hợp con, trong đó chúng ta chỉ phải sử dụng .iloc.

Nhưng hãy thử cả hai để chọn từ một df lớn hơn và hãy kiểm tra tốc độ ...

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

Vì vậy, với .loc chúng ta có thể quản lý các tập hợp con và với .at chỉ một số vô hướng duy nhất, nhưng .at nhanh hơn .loc

:-)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.