Iloc, ix và loc khác nhau như thế nào?


636

Ai đó có thể giải thích ba phương pháp cắt này khác nhau như thế nào không?
Tôi đã xem các tài liệu và tôi đã thấy những câu trả lời này , nhưng tôi vẫn thấy mình không thể giải thích được ba người khác nhau như thế nào. Đối với tôi, chúng dường như có thể hoán đổi cho nhau phần lớn, bởi vì chúng ở mức độ cắt lát thấp hơn.

Ví dụ: giả sử chúng tôi muốn nhận năm hàng đầu tiên của a DataFrame. Làm thế nào mà cả ba trong số này làm việc?

df.loc[:5]
df.ix[:5]
df.iloc[:5]

Ai đó có thể trình bày ba trường hợp mà sự khác biệt trong sử dụng là rõ ràng hơn?


7
rất quan trọng để đề cập đến các kịch bản Cài đặtWithCopyWarning: stackoverflow.com/questions/20625582/ triệt và stackoverflow.com/questions/23688307/ Lỗi
Paul

9
Lưu ý rằng ix hiện được lên kế hoạch
khấu hao

Câu trả lời:


970

Lưu ý: trong gấu trúc phiên bản 0.20.0 trở lên, ixđang bị phản đối và việc sử dụng locilocđược khuyến khích để thay thế. Tôi đã để lại các phần của câu trả lời này mô tả ixnguyên vẹn như một tài liệu tham khảo cho người dùng các phiên bản trước của gấu trúc. Các ví dụ đã được thêm vào dưới đây cho thấy các lựa chọn thay thế ix .


Đầu tiên, đây là bản tóm tắt của ba phương pháp:

  • locđược các hàng (hoặc cột) với các nhãn cụ thể từ chỉ mục.
  • iloclấy các hàng (hoặc cột) tại các vị trí cụ thể trong chỉ mục (vì vậy nó chỉ lấy số nguyên).
  • ixthường cố gắng cư xử như thế locnhưng lại quay lại hành xử như ilocthể nếu một nhãn không có trong chỉ mục.

Điều quan trọng cần lưu ý là một số tinh tế có thể làm cho ixhơi khó sử dụng:

  • nếu chỉ mục thuộc loại số nguyên, ixsẽ chỉ sử dụng lập chỉ mục dựa trên nhãn và không quay lại lập chỉ mục dựa trên vị trí. Nếu nhãn không nằm trong chỉ mục, một lỗi sẽ xuất hiện.

  • nếu chỉ mục không chỉ chứa số nguyên, sau đó được cung cấp một số nguyên, ixsẽ ngay lập tức sử dụng lập chỉ mục dựa trên vị trí thay vì lập chỉ mục dựa trên nhãn. Tuy nhiên, nếu ixđược đưa ra một loại khác (ví dụ: một chuỗi), nó có thể sử dụng lập chỉ mục dựa trên nhãn.


Để minh họa sự khác biệt giữa ba phương pháp, hãy xem xét Sê-ri sau:

>>> s = pd.Series(np.nan, index=[49,48,47,46,45, 1, 2, 3, 4, 5])
>>> s
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN
4    NaN
5    NaN

Chúng ta sẽ xem xét việc cắt lát với giá trị nguyên 3.

Trong trường hợp này, s.iloc[:3]trả về cho chúng tôi 3 hàng đầu tiên (vì nó coi 3 là một vị trí) và s.loc[:3]trả lại cho chúng tôi 8 hàng đầu tiên (vì nó coi 3 là một nhãn):

>>> s.iloc[:3] # slice the first three rows
49   NaN
48   NaN
47   NaN

>>> s.loc[:3] # slice up to and including label 3
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN

>>> s.ix[:3] # the integer is in the index so s.ix[:3] works like loc
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN

Thông báo s.ix[:3]trả về Sê-ri giống như trước s.loc[:3]vì nó tìm nhãn trước thay vì làm việc trên vị trí (và chỉ mục cho slà kiểu số nguyên).

Điều gì xảy ra nếu chúng ta thử với một nhãn số nguyên không có trong chỉ mục (giả sử 6)?

Ở đây s.iloc[:6]trả về 6 hàng đầu tiên của Sê-ri như mong đợi. Tuy nhiên, s.loc[:6]tăng KeyError vì 6không có trong chỉ mục.

>>> s.iloc[:6]
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN

>>> s.loc[:6]
KeyError: 6

>>> s.ix[:6]
KeyError: 6

Theo sự tinh tế đã lưu ý ở trên, s.ix[:6]giờ đây sẽ tăng KeyError vì nó cố gắng hoạt động như thế locnhưng không thể tìm thấy 6trong chỉ mục. Bởi vì chỉ mục của chúng tôi thuộc loại số nguyên ixkhông quay trở lại hoạt động như thế nào iloc.

Tuy nhiên, nếu chỉ mục của chúng tôi thuộc loại hỗn hợp, được cung cấp một số nguyên ixsẽ hoạt động như ilocngay lập tức thay vì tăng KeyError:

>>> s2 = pd.Series(np.nan, index=['a','b','c','d','e', 1, 2, 3, 4, 5])
>>> s2.index.is_mixed() # index is mix of different types
True
>>> s2.ix[:6] # now behaves like iloc given integer
a   NaN
b   NaN
c   NaN
d   NaN
e   NaN
1   NaN

Hãy nhớ rằng ixvẫn có thể chấp nhận những người không phải là số nguyên và hành xử như loc:

>>> s2.ix[:'c'] # behaves like loc given non-integer
a   NaN
b   NaN
c   NaN

Theo lời khuyên chung, nếu bạn chỉ lập chỉ mục bằng cách sử dụng nhãn hoặc chỉ lập chỉ mục bằng cách sử dụng các vị trí số nguyên, hãy gắn bó lochoặc ilocđể tránh kết quả không mong muốn - hãy thử không sử dụng ix.


Kết hợp lập chỉ mục dựa trên vị trí và dựa trên nhãn

Đôi khi được cung cấp một DataFrame, bạn sẽ muốn trộn các phương thức lập chỉ mục nhãn và vị trí cho các hàng và cột.

Ví dụ, hãy xem xét DataFrame sau. Cách tốt nhất để cắt các hàng lên đến và bao gồm 'c' lấy bốn cột đầu tiên?

>>> df = pd.DataFrame(np.nan, 
                      index=list('abcde'),
                      columns=['x','y','z', 8, 9])
>>> df
    x   y   z   8   9
a NaN NaN NaN NaN NaN
b NaN NaN NaN NaN NaN
c NaN NaN NaN NaN NaN
d NaN NaN NaN NaN NaN
e NaN NaN NaN NaN NaN

Trong các phiên bản trước của gấu trúc (trước 0.20.0) ixcho phép bạn thực hiện việc này khá gọn gàng - chúng tôi có thể cắt các hàng theo nhãn và các cột theo vị trí (lưu ý rằng đối với các cột, ixsẽ mặc định là cắt theo vị trí vì 4không phải là tên cột ):

>>> df.ix[:'c', :4]
    x   y   z   8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN

Trong các phiên bản sau của gấu trúc, chúng ta có thể đạt được kết quả này bằng cách sử dụng ilocvà sự trợ giúp của phương pháp khác:

>>> df.iloc[:df.index.get_loc('c') + 1, :4]
    x   y   z   8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN

get_loc()là một phương thức chỉ mục có nghĩa là "có được vị trí của nhãn trong chỉ mục này". Lưu ý rằng vì việc cắt với ilockhông bao gồm điểm cuối của nó, chúng ta phải thêm 1 vào giá trị này nếu chúng ta cũng muốn hàng 'c'.

Có nhiều ví dụ trong tài liệu của gấu trúc ở đây .


12
Giải thích tuyệt vời! Một câu hỏi liên quan mà tôi luôn có là mối quan hệ nào, nếu có, loc, iloc và ix có với các cảnh báo của SetWithCopy không? Có một số tài liệu nhưng thành thật mà nói, tôi vẫn còn một chút bối rối pandas.pydata.org/pandas-docs/ sóng / trộm
đo

3
@measureallthethings : loc, ilocixvẫn có thể kích hoạt cảnh báo nếu chúng bị xích lại với nhau. Sử dụng ví dụ DataFrame trong các tài liệu được liên kết dfmi.loc[:, 'one'].loc[:, 'second']sẽ kích hoạt cảnh báo giống như dfmi['one']['second']vì một bản sao dữ liệu (chứ không phải dạng xem) có thể được trả về bởi thao tác lập chỉ mục đầu tiên.
Alex Riley

Bạn sử dụng cái gì nếu bạn muốn tra cứu Date Index bằng một Ngày, hoặc đại loại như thế df.ix[date, 'Cash']?
cjm2671

@ cjm2671: cả hai lochoặc ixnên hoạt động trong trường hợp đó. Ví dụ: df.loc['2016-04-29', 'Cash']sẽ trả về tất cả các chỉ mục hàng có ngày cụ thể đó từ cột 'Tiền mặt'. (Bạn có thể càng cụ thể càng bạn thích khi lấy chỉ số với chuỗi, ví dụ như '2016-01'sẽ chọn tất cả datetimes rơi vào tháng giêng năm 2016, ` '2016/01/02 11' sẽ chọn datetimes vào ngày 02 tháng 1 năm 2016 với thời gian 11: ??: ?? .)
Alex Riley

Trong trường hợp bạn muốn cập nhật câu trả lời này vào một lúc nào đó, có những gợi ý ở đây về cách sử dụng loc / iloc thay vì ix github.com/pandas-dev/pandas/issues/14218
JohnE

142

ilochoạt động dựa trên định vị số nguyên. Vì vậy, bất kể nhãn hàng của bạn là gì, bạn luôn có thể, ví dụ: lấy hàng đầu tiên bằng cách thực hiện

df.iloc[0]

hoặc năm hàng cuối cùng bằng cách làm

df.iloc[-5:]

Bạn cũng có thể sử dụng nó trên các cột. Điều này lấy ra cột thứ 3:

df.iloc[:, 2]    # the : in the first position indicates all rows

Bạn có thể kết hợp chúng để có giao điểm của các hàng và cột:

df.iloc[:3, :3] # The upper-left 3 X 3 entries (assuming df has 3+ rows and columns)

Mặt khác, .locsử dụng các chỉ số được đặt tên. Hãy thiết lập một khung dữ liệu với các chuỗi dưới dạng nhãn hàng và cột:

df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name'])

Sau đó, chúng ta có thể nhận được hàng đầu tiên bằng cách

df.loc['a']     # equivalent to df.iloc[0]

và hai hàng thứ hai của 'date'cột bằng

df.loc['b':, 'date']   # equivalent to df.iloc[1:, 1]

và như thế. Bây giờ, có lẽ đáng để chỉ ra rằng các chỉ số hàng và cột mặc định cho a DataFramelà các số nguyên từ 0 và trong trường hợp này iloclocsẽ hoạt động theo cùng một cách. Đây là lý do tại sao ba ví dụ của bạn là tương đương. Nếu bạn có một chỉ mục không phải là số như chuỗi hoặc datetimes, df.loc[:5] sẽ gây ra lỗi.

Ngoài ra, bạn có thể thực hiện truy xuất cột chỉ bằng cách sử dụng khung dữ liệu __getitem__:

df['time']    # equivalent to df.loc[:, 'time']

Bây giờ giả sử bạn muốn trộn vị trí và lập chỉ mục được đặt tên, nghĩa là lập chỉ mục bằng cách sử dụng tên trên các hàng và vị trí trên các cột (để làm rõ, ý tôi là chọn từ khung dữ liệu của chúng tôi, thay vì tạo khung dữ liệu với các chuỗi trong chỉ mục hàng và số nguyên trong chỉ số cột). Đây là nơi .ixđến:

df.ix[:2, 'time']    # the first two rows of the 'time' column

Tôi nghĩ điều đáng nói là bạn cũng có thể truyền các vectơ boolean cho locphương thức này. Ví dụ:

 b = [True, False, True]
 df.loc[b] 

Sẽ trả lại hàng thứ 1 và thứ 3 của df. Điều này tương đương df[b]với lựa chọn, nhưng nó cũng có thể được sử dụng để gán thông qua các vectơ boolean:

df.loc[b, 'name'] = 'Mary', 'John'

Df.iloc [:,:] có tương đương với tất cả các hàng và cột không?
Alvis

Nó là, như sẽ được df.loc[:, :]. Nó có thể được sử dụng để gán lại các giá trị của toàn bộ DataFramehoặc tạo ra một khung nhìn của nó.
JoeCondron

xin chào, bạn có biết tại sao loc và iloc lấy tham số ở giữa dấu ngoặc vuông [] mà không phải là một phương thức bình thường ở giữa dấu ngoặc đơn cổ điển () không?
Marine Galantin

119

Theo tôi, câu trả lời được chấp nhận là khó hiểu, vì nó sử dụng DataFrame chỉ có các giá trị bị thiếu. Tôi cũng không thích thuật ngữ vị trí dựa trên cho .ilocvà thay vào đó, thích nguyên vị trí như nó có nhiều tính mô tả hơn và chính xác những gì .iloclà viết tắt của. Từ khóa là INTEGER - .iloccần INTEGERS.

Xem loạt blog cực kỳ chi tiết của tôi về lựa chọn tập hợp con để biết thêm


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

Bởi vì .ixkhông được chấp nhận, chúng tôi sẽ chỉ 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 chỉ mục. 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 cho các chỉ số .


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 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 của DataFrame.

Có ba đầu vào khác nhau mà bạn có thể sử dụng cho .loc

  • 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.

Có ba đầu vào khác nhau mà bạn có thể sử dụng cho .iloc

  • 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ể thực hiện 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ũ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à 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'

6
Ồ, đây là một trong những giải thích rất rõ ràng và sáng suốt mà tôi từng gặp về một chủ đề lập trình, Những gì bạn đã giải thích cuối cùng về lập chỉ mục bình thường hoạt động trên hàng hoặc cột là một trong những lý do chúng tôi có loc và iloc phương pháp. Tôi đã đi qua cảnh báo đó trong khóa học datacamp. a.) Làm gì df.columns và df.index trở lại? Nó có phải là một danh sách các chuỗi? Nếu nó là một danh sách, nó có được phép truy cập hai yếu tố như df.columns [[2,4]] này trong danh sách không? b.) Tôi có thể gọi get_loc () trên df.column không? c.) Tại sao chúng ta cần gọi df ['age']> 30. giá trị trong trường hợp iloc.
pragun

Ansewer tốt nhất mà tôi từng thấy.
Tối đa

Đây là một câu trả lời thực sự tốt, tôi thích rằng nó không nhận được nhiều vào ix, nó bị phản đối và vô nghĩa để lặn sâu. Cảm ơn.
omabena
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.