iloc,ix和loc有何不同?

本文翻译自:How are iloc, ix and loc different?

Can someone explain how these three methods of slicing are different? 有人可以解释这三种切片方法有何不同吗?
I've seen the docs , and I've seen these answers , but I still find myself unable to explain how the three are different. 我看过文档 ,也看过这些 答案 ,但是我仍然发现自己无法解释这三者之间的区别。 To me, they seem interchangeable in large part, because they are at the lower levels of slicing. 在我看来,它们在很大程度上似乎是可互换的,因为它们处于切片的较低级别。

For example, say we want to get the first five rows of a DataFrame . 例如,假设我们要获取DataFrame的前五行。 How is it that all three of these work? 这三者如何运作?

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

Can someone present three cases where the distinction in uses are clearer? 有人可以提出三种用法之间的区别更清楚的情况吗?


#1楼

参考:https://stackoom.com/question/28Ypl/iloc-ix和loc有何不同


#2楼

Note: in pandas version 0.20.0 and above, ix is deprecated and the use of loc and iloc is encouraged instead. 注意:在熊猫版本0.20.0及更高版本中, 不建议使用ix ,而建议使用lociloc I have left the parts of this answer that describe ix intact as a reference for users of earlier versions of pandas. 我保留了完整描述ix的部分答案,以供早期版本的熊猫用户参考。 Examples have been added below showing alternatives to ix . 下面添加了示例,显示了ix替代方案


First, here's a recap of the three methods: 首先,以下是三种方法的概述:

  • loc gets rows (or columns) with particular labels from the index. loc从索引中获取带有特定标签的行(或列)。
  • iloc gets rows (or columns) at particular positions in the index (so it only takes integers). iloc在索引中的特定位置获取行(或列)(因此仅获取整数)。
  • ix usually tries to behave like loc but falls back to behaving like iloc if a label is not present in the index. ix通常会尝试像loc一样表现, iloc如果索引中不存在标签,则会退回到iloc表现。

It's important to note some subtleties that can make ix slightly tricky to use: 重要的是要注意一些会使ix难以使用的微妙之处:

  • if the index is of integer type, ix will only use label-based indexing and not fall back to position-based indexing. 如果索引是整数类型,则ix将仅使用基于标签的索引,而不会使用基于位置的索引。 If the label is not in the index, an error is raised. 如果标签不在索引中,则会引发错误。

  • if the index does not contain only integers, then given an integer, ix will immediately use position-based indexing rather than label-based indexing. 如果指数不包含唯一整数,然后给出一个整数, ix将立即使用基于位置的索引,而不是基于标签的索引。 If however ix is given another type (eg a string), it can use label-based indexing. 但是,如果给ix另一种类型(例如字符串),则可以使用基于标签的索引。


To illustrate the differences between the three methods, consider the following Series: 为了说明这三种方法之间的差异,请考虑以下系列:

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

We'll look at slicing with the integer value 3 . 我们将看一下整数3切片。

In this case, s.iloc[:3] returns us the first 3 rows (since it treats 3 as a position) and s.loc[:3] returns us the first 8 rows (since it treats 3 as a label): 在这种情况下, s.iloc[:3]返回我们的前3行(因为它将3视为位置),而s.loc[:3]返回我们的前8行(因为将3作为标签):

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

Notice s.ix[:3] returns the same Series as s.loc[:3] since it looks for the label first rather than working on the position (and the index for s is of integer type). 通知s.ix[:3]返回相同的系列作为s.loc[:3]因为它看起来为标签第一而不是工作的位置(和用于索引s是整数类型的)。

What if we try with an integer label that isn't in the index (say 6 )? 如果我们尝试使用不在索引中的整数标签(例如6 )怎么办?

Here s.iloc[:6] returns the first 6 rows of the Series as expected. 此处s.iloc[:6]返回Series的前6行。 However, s.loc[:6] raises a KeyError since 6 is not in the index. 但是, s.loc[:6]会引发s.loc[:6]因为索引中没有6

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

As per the subtleties noted above, s.ix[:6] now raises a KeyError because it tries to work like loc but can't find a 6 in the index. 按照上面提到的s.ix[:6]s.ix[:6]现在引发s.ix[:6]因为它试图像loc一样工作,但是在索引中找不到6 Because our index is of integer type ix doesn't fall back to behaving like iloc . 因为我们的索引是整数类型ix所以不会像iloc那样iloc

If, however, our index was of mixed type, given an integer ix would behave like iloc immediately instead of raising a KeyError: 但是,如果索引是混合类型的,给定整数ix行为将立即类似于iloc ,而不是引发iloc

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

Keep in mind that ix can still accept non-integers and behave like loc : 请记住, ix仍然可以接受非整数并且行为类似于loc

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

As general advice, if you're only indexing using labels, or only indexing using integer positions, stick with loc or iloc to avoid unexpected results - try not use ix . 作为一般建议,如果仅使用标签建立索引,或仅使用整数位置建立索引,请坚持使用lociloc以避免意外的结果-请勿使用ix


Combining position-based and label-based indexing 结合基于位置和基于标签的索引

Sometimes given a DataFrame, you will want to mix label and positional indexing methods for the rows and columns. 有时给定一个DataFrame,您将需要为行和列混合使用标签和位置索引方法。

For example, consider the following DataFrame. 例如,考虑以下DataFrame。 How best to slice the rows up to and including 'c' and take the first four columns? 如何最好地将行切成“ c” 包括前四列?

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

In earlier versions of pandas (before 0.20.0) ix lets you do this quite neatly - we can slice the rows by label and the columns by position (note that for the columns, ix will default to position-based slicing since 4 is not a column name): 在较早版本的pandas(0.20.0之前)中, ix可以使您非常整洁地执行此操作-我们可以按标签对行进行切片,并按位置对列进行切片(请注意,对于列, ix将默认为基于位置的切片,因为4不是列名):

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

In later versions of pandas, we can achieve this result using iloc and the help of another method: 在更高版本的熊猫中,我们可以使用iloc和另一种方法的帮助来实现此结果:

>>> 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() is an index method meaning "get the position of the label in this index". get_loc()是一个索引方法,意思是“获取标签在此索引中的位置”。 Note that since slicing with iloc is exclusive of its endpoint, we must add 1 to this value if we want row 'c' as well. 请注意,由于使用iloc切片不包括其端点,因此如果还要行'c',则必须在此值上加1。

There are further examples in pandas' documentation here . 此处的熊猫文档中还有其他示例。


#3楼

iloc works based on integer positioning. iloc基于整数定位。 So no matter what your row labels are, you can always, eg, get the first row by doing 因此,无论您的行标签是什么,您都可以始终执行以下操作:

df.iloc[0]

or the last five rows by doing 或最后五行

df.iloc[-5:]

You can also use it on the columns. 您也可以在列上使用它。 This retrieves the 3rd column: 这将检索第三列:

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

You can combine them to get intersections of rows and columns: 您可以将它们结合起来以获得行和列的交集:

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

On the other hand, .loc use named indices. 另一方面, .loc使用命名索引。 Let's set up a data frame with strings as row and column labels: 让我们设置一个带有字符串作为行和列标签的数据框:

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

Then we can get the first row by 然后我们可以得到第一行

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

and the second two rows of the 'date' column by 'date'列的后两行

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

and so on. 等等。 Now, it's probably worth pointing out that the default row and column indices for a DataFrame are integers from 0 and in this case iloc and loc would work in the same way. 现在,可能值得指出的是, DataFrame的默认行和列索引是从0 DataFrame的整数,在这种情况下, ilocloc将以相同的方式工作。 This is why your three examples are equivalent. 这就是为什么您的三个示例是等效的。 If you had a non-numeric index such as strings or datetimes, df.loc[:5] would raise an error. 如果您有非数字索引,例如字符串或日期时间,则 df.loc[:5] 会引发错误。

Also, you can do column retrieval just by using the data frame's __getitem__ : 另外,您可以仅使用数据框的__getitem__进行列检索:

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

Now suppose you want to mix position and named indexing, that is, indexing using names on rows and positions on columns (to clarify, I mean select from our data frame, rather than creating a data frame with strings in the row index and integers in the column index). 现在假设您要混合使用位置索引和命名索引,即使用行上的名称和列上的位置进行索引(为了澄清,我的意思是从我们的数据框中进行选择,而不是创建一个在行索引中包含字符串而在其中包含整数的数据框架列索引)。 This is where .ix comes in: 这是.ix来源:

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

I think it's also worth mentioning that you can pass boolean vectors to the loc method as well. 我认为也值得一提的是,您也可以将布尔向量传递给loc方法。 For example: 例如:

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

Will return the 1st and 3rd rows of df . 将返回df的第一行和第三行。 This is equivalent to df[b] for selection, but it can also be used for assigning via boolean vectors: 这等效于df[b]进行选择,但也可以用于通过布尔向量进行分配:

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

#4楼

In my opinion, the accepted answer is confusing, since it uses a DataFrame with only missing values. 我认为,可接受的答案令人困惑,因为它使用仅缺少值的DataFrame。 I also do not like the term position-based for .iloc and instead, prefer integer location as it is much more descriptive and exactly what .iloc stands for. 我也不太喜欢.iloc的术语基于位置的术语,而是更喜欢整数位置,因为它更具描述性,并且确切地代表.iloc The key word is INTEGER - .iloc needs INTEGERS. 关键字是INTEGER- .iloc需要INTEGERS。

See my extremely detailed blog series on subset selection for more 请参阅我关于子集选择的非常详细的博客系列 ,以了解更多信息


.ix is deprecated and ambiguous and should never be used .ix已弃用且含糊不清,切勿使用

Because .ix is deprecated we will only focus on the differences between .loc and .iloc . 由于.ix已弃用,因此我们仅关注.loc.iloc之间的差异。

Before we talk about the differences, it is important to understand that DataFrames have labels that help identify each column and each index. 在讨论差异之前,重要的是要了解DataFrame具有用于帮助标识每个列和每个索引的标签。 Let's take a look at a sample DataFrame: 让我们看一个示例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'])

在此处输入图片说明

All the words in bold are the labels. 所有粗体字均为标签。 The labels, age , color , food , height , score and state are used for the columns . 标签, agecolorfoodheightscorestate被用于 The other labels, Jane , Nick , Aaron , Penelope , Dean , Christina , Cornelia are used for the index . 索引使用其他标签,例如JaneNickAaronPenelopeDeanChristinaCornelia


The primary ways to select particular rows in a DataFrame are with the .loc and .iloc indexers. 在DataFrame中选择特定行的主要方法是使用.loc.iloc索引器。 Each of these indexers can also be used to simultaneously select columns but it is easier to just focus on rows for now. 这些索引器中的每一个也可以用于同时选择列,但是现在只关注行比较容易。 Also, each of the indexers use a set of brackets that immediately follow their name to make their selections. 此外,每个索引器都使用紧跟其名称的一组括号来进行选择。

.loc selects data only by labels .loc仅通过标签选择数据

We will first talk about the .loc indexer which only selects data by the index or column labels. 我们将首先讨论.loc索引器,该索引器仅通过索引或列标签选择数据。 In our sample DataFrame, we have provided meaningful names as values for the index. 在示例DataFrame中,我们提供了有意义的名称作为索引值。 Many DataFrames will not have any meaningful names and will instead, default to just the integers from 0 to n-1, where n is the length of the DataFrame. 许多DataFrame都没有任何有意义的名称,而是默认为0到n-1之间的整数,其中n是DataFrame的长度。

There are three different inputs you can use for .loc .loc可以使用三种不同的输入

  • A string 一串
  • A list of strings 字符串列表
  • Slice notation using strings as the start and stop values 使用字符串作为起始值和终止值的切片符号

Selecting a single row with .loc with a string 用带字符串的.loc选择单行

To select a single row of data, place the index label inside of the brackets following .loc . 要选择一行数据,请将索引标签放在.loc之后的括号内。

df.loc['Penelope']

This returns the row of data as a Series 这将数据行作为系列返回

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

Selecting multiple rows with .loc with a list of strings 使用.loc与字符串列表选择多行

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

This returns a DataFrame with the rows in the order specified in the list: 这将返回一个DataFrame,其中的数据行按列表中指定的顺序进行:

在此处输入图片说明

Selecting multiple rows with .loc with slice notation 使用带有切片符号的.loc选择多行

Slice notation is defined by a start, stop and step values. 切片符号由开始,停止和步进值定义。 When slicing by label, pandas includes the stop value in the return. 按标签切片时,大熊猫在返回值中包含停止值。 The following slices from Aaron to Dean, inclusive. 以下是从亚伦到迪恩(含)的片段。 Its step size is not explicitly defined but defaulted to 1. 它的步长未明确定义,但默认为1。

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

在此处输入图片说明

Complex slices can be taken in the same manner as Python lists. 可以采用与Python列表相同的方式获取复杂的切片。

.iloc selects data only by integer location .iloc仅按整数位置选择数据

Let's now turn to .iloc . 现在转到.iloc Every row and column of data in a DataFrame has an integer location that defines it. DataFrame中数据的每一行和每一列都有一个定义它的整数位置。 This is in addition to the label that is visually displayed in the output . 这是在输出中直观显示的标签的补充 The integer location is simply the number of rows/columns from the top/left beginning at 0. 整数位置只是从0开始从顶部/左侧开始的行/列数。

There are three different inputs you can use for .iloc .iloc可以使用三种不同的输入

  • An integer 一个整数
  • A list of integers 整数列表
  • Slice notation using integers as the start and stop values 使用整数作为起始值和终止值的切片符号

Selecting a single row with .iloc with an integer 用带整数的.iloc选择单行

df.iloc[4]

This returns the 5th row (integer location 4) as a Series 这将返回第5行(整数位置4)为系列

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

Selecting multiple rows with .iloc with a list of integers 用.iloc选择带有整数列表的多行

df.iloc[[2, -2]]

This returns a DataFrame of the third and second to last rows: 这将返回第三行和倒数第二行的DataFrame:

在此处输入图片说明

Selecting multiple rows with .iloc with slice notation 使用带切片符号的.iloc选择多行

df.iloc[:5:3]

在此处输入图片说明


Simultaneous selection of rows and columns with .loc and .iloc 使用.loc和.iloc同时选择行和列

One excellent ability of both .loc/.iloc is their ability to select both rows and columns simultaneously. .loc/.iloc一项出色功能是它们可以同时选择行和列。 In the examples above, all the columns were returned from each selection. 在上面的示例中,所有列都是从每个选择中返回的。 We can choose columns with the same types of inputs as we do for rows. 我们可以选择输入类型与行相同的列。 We simply need to separate the row and column selection with a comma . 我们只需要用逗号分隔行和列选择即可。

For example, we can select rows Jane, and Dean with just the columns height, score and state like this: 例如,我们可以选择Jane行和Dean行,它们的高度,得分和状态如下:

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

在此处输入图片说明

This uses a list of labels for the rows and slice notation for the columns 这对行使用标签列表,对列使用切片符号

We can naturally do similar operations with .iloc using only integers. 我们自然可以只使用整数对.iloc进行类似的操作。

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

Simultaneous selection with labels and integer location 带标签和整数位置的同时选择

.ix was used to make selections simultaneously with labels and integer location which was useful but confusing and ambiguous at times and thankfully it has been deprecated. .ix用于同时与标签和整数位置进行选择,这虽然有用,但有时会造成混淆和模棱两可,值得庆幸的是,它已被弃用。 In the event that you need to make a selection with a mix of labels and integer locations, you will have to make both your selections labels or integer locations. 如果您需要混合使用标签和整数位置进行选择,则必须同时选择标签或整数位置。

For instance, if we want to select rows Nick and Cornelia along with columns 2 and 4, we could use .loc by converting the integers to labels with the following: 例如,如果我们要选择行NickCornelia以及列2和4,我们可以使用.loc通过将整数转换为带有以下内容的标签:

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

Or alternatively, convert the index labels to integers with the get_loc index method. 或者,可以使用get_loc index方法将索引标签转换为整数。

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

Boolean Selection 布尔选择

The .loc indexer can also do boolean selection. .loc索引器还可以进行布尔选择。 For instance, if we are interested in finding all the rows wher age is above 30 and return just the food and score columns we can do the following: 例如,如果我们有兴趣查找年龄在30岁以上的所有行,并仅返回foodscore列,则可以执行以下操作:

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

You can replicate this with .iloc but you cannot pass it a boolean series. 您可以使用.iloc复制此文件,但不能将其传递为布尔系列。 You must convert the boolean Series into a numpy array like this: 您必须将boolean Series转换为numpy数组,如下所示:

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

Selecting all rows 选择所有行

It is possible to use .loc/.iloc for just column selection. 可以将.loc/.iloc用于仅列选择。 You can select all the rows by using a colon like this: 您可以使用如下冒号来选择所有行:

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

在此处输入图片说明


The indexing operator, [] , can select rows and columns too but not simultaneously. 索引运算符[]也可以选择行和列,但不能同时选择。

Most people are familiar with the primary purpose of the DataFrame indexing operator, which is to select columns. 大多数人都熟悉DataFrame索引运算符的主要目的,即选择列。 A string selects a single column as a Series and a list of strings selects multiple columns as a DataFrame. 字符串选择单个列作为系列,而字符串列表选择多个列作为DataFrame。

df['food']

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

Using a list selects multiple columns 使用列表选择多个列

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

在此处输入图片说明

What people are less familiar with, is that, when slice notation is used, then selection happens by row labels or by integer location. 人们所不熟悉的是,当使用切片符号时,选择是通过行标签或整数位置进行的。 This is very confusing and something that I almost never use but it does work. 这非常令人困惑,我几乎从未使用过,但是确实可以使用。

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

在此处输入图片说明

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

在此处输入图片说明

The explicitness of .loc/.iloc for selecting rows is highly preferred. 强烈建议使用.loc/.iloc来选择行。 The indexing operator alone is unable to select rows and columns simultaneously. 单独的索引运算符无法同时选择行和列。

df[3:5, 'color']
TypeError: unhashable type: 'slice'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值