How are iloc, ix and loc different?
有人能解释一下这三种切片方法有什么不同吗?我看过医生,我已经看到了这些答案,但我仍然无法解释这三个答案的不同之处。在我看来,它们在很大程度上是可以互换的,因为它们处于较低的切片级别。
例如,假设我们想要得到一个
1 2 3 | df.loc[:5] df.ix[:5] df.iloc[:5] |
有人能提出三种使用上的区别更清楚的情况吗?
注:熊猫0.20.0及以上版本不推荐使用
首先,这里简要介绍三种方法:
loc 从索引中获取带有特定标签的行(或列)。iloc 在索引中的特定位置获取行(或列)(因此它只接受整数)。ix 通常试图表现得像loc ,但如果索引中没有标签,则会回到iloc 的表现。
重要的是要注意一些细微之处,这些细微之处会使
如果索引是整数类型,那么
ix 将只使用基于标签的索引,而不返回基于位置的索引。如果标签不在索引中,则会引发错误。如果索引不只包含整数,那么给定一个整数,
ix 将立即使用基于位置的索引,而不是基于标签的索引。但是,如果ix 被赋予另一种类型(例如字符串),它可以使用基于标签的索引。
为了说明这三种方法之间的差异,请考虑以下系列:
1 2 3 4 5 6 7 8 9 10 11 12 | >>> 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 |
我们来看看整型值
在这种情况下,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | >>> 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 |
号
注意,
如果我们尝试使用一个不在索引中的整数标签(比如
这里,
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> 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 |
根据上面提到的微妙之处,
但是,如果我们的索引是混合类型的,如果给定一个整数
1 2 3 4 5 6 7 8 9 10 | >>> 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 |
。
记住,
1 2 3 4 | >>> s2.ix[:'c'] # behaves like loc given non-integer a NaN b NaN c NaN |
作为一般建议,如果您只使用标签进行索引,或者只使用整数位置进行索引,请使用
有时,如果给定了一个数据帧,您将希望为行和列混合使用标签和位置索引方法。
例如,考虑以下数据帧。如何最好地将行切片到"c"并包括"c",并取前四列?
1 2 3 4 5 6 7 8 9 10 | >>> 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 |
。
在早期版本的pandas(0.20.0之前)中,
1 2 3 4 5 | >>> df.ix[:'c', :4] x y z 8 a NaN NaN NaN NaN b NaN NaN NaN NaN c NaN NaN NaN NaN |
。
在以后的熊猫版本中,我们可以使用
1 2 3 4 5 | >>> 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 |
在熊猫的文档中还有更多的例子。
1 | df.iloc[0] |
或者做最后五行
1 | df.iloc[-5:] |
号
您也可以在列中使用它。这将检索第3列:
1 | df.iloc[:, 2] # the : in the first position indicates all rows |
您可以组合它们以获得行和列的交叉点:
1 | df.iloc[:3, :3] # The upper-left 3 X 3 entries (assuming df has 3+ rows and columns) |
。
另一方面,
1 | df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name']) |
那我们就可以坐第一排了
1 | df.loc['a'] # equivalent to df.iloc[0] |
。
和第二行的
1 | df.loc['b':, 'date'] # equivalent to df.iloc[1:, 1] |
。
等等。现在,有必要指出,
另外,只需使用数据帧的
1 | df['time'] # equivalent to df.loc[:, 'time'] |
现在假设您想混合使用位置和命名索引,也就是说,使用行上的名称和列上的位置进行索引(为了澄清,我的意思是从数据帧中选择,而不是创建一个数据帧,其中行索引中包含字符串,列索引中包含整数)。这就是
1 | df.ix[:2, 'time'] # the first two rows of the 'time' column |
。
我认为也值得一提的是,您可以将布尔向量传递给
1 2 | b = [True, False, True] df.loc[b] |
将返回
1 | df.loc[b, 'name'] = 'Mary', 'John' |
。
在我看来,接受的答案令人困惑,因为它使用的是一个只缺少值的数据帧。我也不喜欢基于
有关子集选择的详细信息,请参阅我的博客系列。好的。.ix已弃用且不明确,不应使用
由于
在我们讨论差异之前,重要的是要理解数据帧具有帮助识别每个列和每个索引的标签。让我们来看一个示例数据框:好的。
1 2 3 4 5 6 7 8 | 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']) |
。好的。
粗体字都是标签。列使用标签:
选择数据帧中特定行的主要方法是使用
我们将首先讨论
有三种不同的输入可用于
- 一根绳子
- 字符串列表
- 以字符串作为起始值和终止值的切片表示法
选择带有.loc和字符串的单行好的。
要选择一行数据,请将索引标签放在
1 | df.loc['Penelope'] |
号
这将以序列形式返回数据行好的。
1 2 3 4 5 6 7 | age 4 color white food Apple height 80 score 3.3 state AL Name: Penelope, dtype: object |
使用.loc和字符串列表选择多行好的。
1 | df.loc[['Cornelia', 'Jane', 'Dean']] |
。
这将返回一个数据帧,其中的行按列表中指定的顺序排列:好的。
氧化镁好的。
用.loc和slice符号选择多行好的。
切片表示法由开始、停止和步骤值定义。当按标签切片时,pandas在返回中包含stop值。以下是从Aaron到Dean的片段。其步骤大小未明确定义,但默认为1。好的。
1 | df.loc['Aaron':'Dean'] |
氧化镁好的。
复杂切片可以采用与Python列表相同的方式。好的。.iloc仅按整数位置选择数据
现在我们来看看
有三种不同的输入可用于
- 整数
- 整数列表
- 以整数作为起始值和终止值的切片表示法
用带整数的.iloc选择一行好的。
1 | df.iloc[4] |
这将返回第5行(整数位置4)作为一个序列好的。
1 2 3 4 5 6 7 | age 32 color gray food Cheese height 180 score 1.8 state AK Name: Dean, dtype: object |
号
用.iloc和整数列表选择多行好的。
1 | df.iloc[[2, -2]] |
这将返回第三行和第二行到最后一行的数据帧:好的。
。好的。
使用.iloc和slice符号选择多行好的。
1 | df.iloc[:5:3] |
。
氧化镁好的。使用.loc和.iloc同时选择行和列
两个
例如,我们可以选择行Jane和Dean,只选择列高度、分数和状态,如下所示:好的。
1 | df.loc[['Jane', 'Dean'], 'height':] |
氧化镁好的。
这将使用行的标签列表和列的切片表示法好的。
我们可以自然地用
1 2 3 4 | df.iloc[[1,4], 2] Nick Lamb Dean Cheese Name: food, dtype: object |
。同时选择标签和整数位置
例如,如果我们要选择行
1 2 | col_names = df.columns[[2, 4]] df.loc[['Nick', 'Cornelia'], col_names] |
。
或者,使用
1 2 3 | labels = ['Nick', 'Cornelia'] index_ints = [df.index.get_loc(label) for label in labels] df.iloc[index_ints, [2, 4]] |
布尔选择
.loc索引器也可以进行布尔选择。例如,如果我们有兴趣查找年龄在30岁以上的所有行,只返回
1 | df.loc[df['age'] > 30, ['food', 'score']] |
。
您可以用
1 | df.iloc[(df['age'] > 30).values, [2, 4]] |
选择所有行
可以使用
1 | df.loc[:, 'color':'score':2] |
。
氧化镁好的。索引操作符
大多数人都熟悉数据帧索引操作符的主要用途,即选择列。字符串选择单个列作为序列,字符串列表选择多个列作为数据帧。好的。
1 2 3 4 5 6 7 8 9 10 | df['food'] Jane Steak Nick Lamb Aaron Mango Penelope Apple Dean Cheese Christina Melon Cornelia Beans Name: food, dtype: object |
使用列表可选择多列好的。
1 | df[['food', 'score']] |
号
。好的。
人们不太熟悉的是,当使用切片表示法时,选择是通过行标签或整数位置进行的。这是非常混乱的,我几乎从未使用过,但它确实有效。好的。
1 | df['Penelope':'Christina'] # slice rows by label |
氧化镁好的。
1 | df[2:6:2] # slice rows by integer location |
。
氧化镁好的。
选择行时最好使用
1 2 | df[3:5, 'color'] TypeError: unhashable type: 'slice' |
好啊。