有人能解释一下这两种切片方法有什么不同吗? 我看过医生了 我看到了这些答案,但我仍然无法理解这三个答案有什么不同。对我来说,它们在很大程度上是可以互换的,因为它们处于较低的切片水平。
例如,假设我们想获取一个DataFrame的前五行。这两者是如何运作的呢?
df.loc[:5]
df.iloc[:5]
谁能举出三种用法上的区别更清楚的例子?
以前,我还想知道这两个函数和df有什么不同。ix[:5]但是ix已经从pandas 1.0中删除了,所以我不再关心了。
有人能解释一下这两种切片方法有什么不同吗? 我看过医生了 我看到了这些答案,但我仍然无法理解这三个答案有什么不同。对我来说,它们在很大程度上是可以互换的,因为它们处于较低的切片水平。
例如,假设我们想获取一个DataFrame的前五行。这两者是如何运作的呢?
df.loc[:5]
df.iloc[:5]
谁能举出三种用法上的区别更清楚的例子?
以前,我还想知道这两个函数和df有什么不同。ix[:5]但是ix已经从pandas 1.0中删除了,所以我不再关心了。
标签vs.位置
这两种方法的主要区别是:
Loc获取带有特定标签的行(和/或列)。 Iloc在整数位置获取行(和/或列)。
为了演示,考虑一系列具有非单调整数索引的字符s:
>>> s = pd.Series(list("abcdef"), index=[49, 48, 47, 0, 1, 2])
49 a
48 b
47 c
0 d
1 e
2 f
>>> s.loc[0] # value at index label 0
'd'
>>> s.iloc[0] # value at index location 0
'a'
>>> s.loc[0:1] # rows at index labels between 0 and 1 (inclusive)
0 d
1 e
>>> s.iloc[0:1] # rows at index location between 0 and 1 (exclusive)
49 a
下面是s.loc和s.iloc在传递各种对象时的一些不同/相似之处:
<object> | description | s.loc[<object>] |
s.iloc[<object>] |
---|---|---|---|
0 |
single item | Value at index label 0 (the string 'd' ) |
Value at index location 0 (the string 'a' ) |
0:1 |
slice | Two rows (labels 0 and 1 ) |
One row (first row at location 0) |
1:47 |
slice with out-of-bounds end | Zero rows (empty Series) | Five rows (location 1 onwards) |
1:47:-1 |
slice with negative step | three rows (labels 1 back to 47 ) |
Zero rows (empty Series) |
[2, 0] |
integer list | Two rows with given labels | Two rows with given locations |
s > 'e' |
Bool series (indicating which values have the property) | One row (containing 'f' ) |
NotImplementedError |
(s>'e').values |
Bool array | One row (containing 'f' ) |
Same as loc |
999 |
int object not in index | KeyError |
IndexError (out of bounds) |
-1 |
int object not in index | KeyError |
Returns last value in s |
lambda x: x.index[3] |
callable applied to series (here returning 3rd item in index) | s.loc[s.index[3]] |
s.iloc[s.index[3]] |
Loc的标签查询功能远远超出了整数索引的范围,有必要再举几个例子。
下面是一个索引包含字符串对象的Series:
>>> s2 = pd.Series(s.index, index=s.values)
>>> s2
a 49
b 48
c 47
d 0
e 1
f 2
由于loc是基于标签的,它可以使用s2.loc['a']获取Series中的第一个值。它也可以对非整数对象进行切片:
>>> s2.loc['c':'e'] # all rows lying between 'c' and 'e' (inclusive)
c 47
d 0
e 1
对于DateTime索引,我们不需要通过标签来获取准确的日期/时间。例如:
>>> s3 = pd.Series(list('abcde'), pd.date_range('now', periods=5, freq='M'))
>>> s3
2021-01-31 16:41:31.879768 a
2021-02-28 16:41:31.879768 b
2021-03-31 16:41:31.879768 c
2021-04-30 16:41:31.879768 d
2021-05-31 16:41:31.879768 e
然后获取2021年3月/ 4月的行,我们只需要:
>>> s3.loc['2021-03':'2021-04']
2021-03-31 17:04:30.742316 c
2021-04-30 17:04:30.742316 d
行和列
loc和iloc处理dataframe的方式与处理Series的方式相同。值得注意的是,这两种方法都可以同时寻址列和行。
给定一个元组时,第一个元素用于索引行,如果存在,第二个元素用于索引列。
考虑下面定义的数据帧:
>>> import numpy as np
>>> df = pd.DataFrame(np.arange(25).reshape(5, 5),
index=list('abcde'),
columns=['x','y','z', 8, 9])
>>> df
x y z 8 9
a 0 1 2 3 4
b 5 6 7 8 9
c 10 11 12 13 14
d 15 16 17 18 19
e 20 21 22 23 24
然后举个例子:
>>> df.loc['c': , :'z'] # rows 'c' and onwards AND columns up to 'z'
x y z
c 10 11 12
d 15 16 17
e 20 21 22
>>> df.iloc[:, 3] # all rows, but only the column at index location 3
a 3
b 8
c 13
d 18
e 23
有时,我们希望将行和列的标签和位置索引方法混合使用,以某种方式结合loc和iloc的功能。
例如,考虑以下DataFrame。如何最好地将行切片到并包括“c”并取前四列?
>>> import numpy as np
>>> df = pd.DataFrame(np.arange(25).reshape(5, 5),
index=list('abcde'),
columns=['x','y','z', 8, 9])
>>> df
x y z 8 9
a 0 1 2 3 4
b 5 6 7 8 9
c 10 11 12 13 14
d 15 16 17 18 19
e 20 21 22 23 24
我们可以使用iloc和另一个方法来实现这个结果:
>>> df.iloc[:df.index.get_loc('c') + 1, :4]
x y z 8
a 0 1 2 3
b 5 6 7 8
c 10 11 12 13
Get_loc()是一个索引方法,意思是“获取标签在这个索引中的位置”。注意,由于使用iloc进行切片不包含它的端点,如果我们也想要行'c',我们必须在这个值上加上1。
Iloc基于整数定位工作。所以不管你的行标签是什么,你总是可以,例如,通过做
df.iloc[0]
或者最后五行
df.iloc[-5:]
您也可以在列上使用它。这将检索第3列:
df.iloc[:, 2] # the : in the first position indicates all rows
你可以把它们组合起来得到行和列的交点:
df.iloc[:3, :3] # The upper-left 3 X 3 entries (assuming df has 3+ rows and columns)
另一方面,.loc使用命名索引。让我们建立一个以字符串作为行和列标签的数据帧:
df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name'])
然后我们可以得到第一行
df.loc['a'] # equivalent to df.iloc[0]
“date”列的后两行by
df.loc['b':, 'date'] # equivalent to df.iloc[1:, 1]
等等。现在,可能值得指出的是,DataFrame的默认行索引和列索引是从0开始的整数,在这种情况下iloc和loc将以相同的方式工作。这就是为什么你的三个例子是等价的。如果您有一个非数字索引,如字符串或日期时间,df。Loc[:5]将引发一个错误。
同样,你也可以通过使用数据帧的__getitem__来进行列检索:
df['time'] # equivalent to df.loc[:, 'time']
现在假设您想混合使用位置索引和命名索引,也就是说,在行上使用名称,在列上使用位置(澄清一下,我指的是从数据帧中选择,而不是创建一个行索引中有字符串、列索引中有整数的数据帧)。这就是.ix的用武之地:
df.ix[:2, 'time'] # the first two rows of the 'time' column
值得一提的是,你也可以将布尔向量传递给loc方法。例如:
b = [True, False, True]
df.loc[b]
将返回df的第1行和第3行。这相当于df[b]的选择,但它也可以用于通过布尔向量赋值:
df.loc[b, 'name'] = 'Mary', 'John'
在我看来,公认的答案是令人困惑的,因为它使用了一个只有缺失值的DataFrame。我也不喜欢基于位置的术语。iloc,相反,我更喜欢整数位置,因为它更具有描述性,也更准确地代表。iloc。关键字是INTEGER - .iloc需要整数。
更多信息请参阅我关于子集选择的极其详细的博客系列
.ix已弃用且具有歧义,永远不应该使用
由于.ix已弃用,我们将只关注.loc和.iloc之间的差异。
在讨论它们的区别之前,了解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'])
所有加粗的字都是标签。这些列使用标签、年龄、颜色、食物、身高、分数和状态。其他的标签,简,尼克,亚伦,佩内洛普,迪恩,克里斯蒂娜,科妮莉亚被用于索引。
在DataFrame中选择特定行的主要方法是使用.loc和.iloc索引器。每一个索引器都可以用来同时选择列,但是现在只关注行更容易。此外,每个索引器都使用一组括号,紧跟着他们的名字来进行选择。
.loc只根据标签选择数据
我们将首先讨论.loc索引器,它只根据索引或列标签选择数据。在我们的示例DataFrame中,我们提供了有意义的名称作为索引值。许多DataFrame没有任何有意义的名称,而是默认为从0到n-1的整数,其中n是DataFrame的长度。
有三种不同的输入可以用于.loc
一个字符串 字符串列表 使用字符串作为开始值和停止值的切片表示法
选择带有.loc字符串的单行
要选择单行数据,请将索引标签放在.loc后面的括号内。
df.loc['Penelope']
这将以Series的形式返回数据行
age 4
color white
food Apple
height 80
score 3.3
state AL
Name: Penelope, dtype: object
使用.loc和字符串列表选择多行
df.loc[['Cornelia', 'Jane', 'Dean']]
返回一个DataFrame,按列表中指定的行顺序排列:
使用切片符号的.loc选择多行
切片表示法由开始值、停止值和步长值定义。当按标签切片时,pandas在返回值中包含停止值。以下是艾伦写给迪恩的片段,包括在内。它的步长没有明确定义,但默认为1。
df.loc['Aaron':'Dean']
复杂片可以以与Python列表相同的方式获取。
.iloc仅根据整数位置选择数据
现在让我们转向.iloc。DataFrame中的每一行和每一列数据都有一个定义它的整数位置。这是在输出中可视显示的标签之外。整数位置就是从上/左开始从0开始的行数/列数。
有三种不同的输入可以用于.iloc
一个整数 整数列表 使用整数作为开始值和停止值的切片表示法
选择带有整数的.iloc的单行
df.iloc[4]
这将返回第5行(整数位置4)作为一个Series
age 32
color gray
food Cheese
height 180
score 1.8
state AK
Name: Dean, dtype: object
使用.iloc和整数列表选择多行
df.iloc[[2, -2]]
返回第三行和倒数第二行的数据帧:
使用.iloc和切片符号选择多行
df.iloc[:5:3]
使用.loc和.iloc同时选择行和列
两个.loc/的一个出色的能力。Iloc是他们同时选择行和列的能力。在上面的示例中,从每个选择返回所有列。我们可以选择输入类型与行相同的列。我们只需要用逗号分隔行和列的选择。
例如,我们可以选择行Jane和Dean,只使用列的高度、分数和状态,如下所示:
df.loc[['Jane', 'Dean'], 'height':]
它对行使用标签列表,对列使用切片符号
我们自然可以只使用整数对.iloc执行类似的操作。
df.iloc[[1,4], 2]
Nick Lamb
Dean Cheese
Name: food, dtype: object
同时选择标签和整数定位
.ix用于同时使用标签和整数定位进行选择,这很有用,但有时会令人困惑和模糊,幸运的是,它已经被弃用了。如果需要混合使用标签和整数位置进行选择,则必须同时使用标签或整数位置。
例如,如果我们想选择行Nick和Cornelia以及列2和4,我们可以使用.loc将整数转换为标签,如下所示:
col_names = df.columns[[2, 4]]
df.loc[['Nick', 'Cornelia'], col_names]
或者,使用get_loc索引方法将索引标签转换为整数。
labels = ['Nick', 'Cornelia']
index_ints = [df.index.get_loc(label) for label in labels]
df.iloc[index_ints, [2, 4]]
布尔选择
.loc索引器也可以进行布尔选择。例如,如果我们想找到年龄大于30的所有行,只返回食物和分数列,我们可以这样做:
df.loc[df['age'] > 30, ['food', 'score']]
您可以使用.iloc复制此操作,但不能传递布尔序列。你必须像这样将布尔系列转换为numpy数组:
df.iloc[(df['age'] > 30).values, [2, 4]]
选择所有行
可以使用.loc/。Iloc只用于列选择。你可以像这样用冒号选择所有的行:
df.loc[:, 'color':'score':2]
索引操作符[]也可以选择行和列,但不能同时选择。
大多数人都熟悉DataFrame索引操作符的主要用途,即选择列。字符串选择单列作为Series,字符串列表选择多个列作为DataFrame。
df['food']
Jane Steak
Nick Lamb
Aaron Mango
Penelope Apple
Dean Cheese
Christina Melon
Cornelia Beans
Name: food, dtype: object
使用列表可以选择多个列
df[['food', 'score']]
人们不太熟悉的是,当使用切片表示法时,选择是通过行标签或整数位置进行的。这是非常令人困惑的,我几乎从来没有用过,但它确实有用。
df['Penelope':'Christina'] # slice rows by label
df[2:6:2] # slice rows by integer location
.loc/的显式。优先使用Iloc来选择行。索引操作符本身无法同时选择行和列。
df[3:5, 'color']
TypeError: unhashable type: 'slice'
DataFrame.loc():根据索引值选择行 DataFrame.iloc():按行数选择行
例子:
选择表的前5行,df1是你的数据帧
df1.iloc[:5]
选择表的前A, B行,df1是你的数据帧
df1.loc['A','B']
.loc和.iloc用于索引,即提取部分数据。本质上,区别在于.loc允许基于标签的索引,而.iloc允许基于位置的索引。
如果你对.loc和.iloc感到困惑,请记住。iloc基于索引(从i开始)位置,而.loc基于标签(从l开始)。
.loc
.loc应该基于索引标签而不是位置,因此它类似于Python基于字典的索引。但是,它可以接受布尔数组、切片和标签列表(这些都不能用于Python字典)。
iloc
.iloc基于索引位置进行查找,也就是说,pandas的行为类似于Python列表。如果在该位置没有索引,pandas将引发IndexError。
例子
下面的例子说明了.iloc和.loc之间的区别。让我们考虑以下系列:
>>> s = pd.Series([11, 9], index=["1990", "1993"], name="Magic Numbers")
>>> s
1990 11
1993 9
Name: Magic Numbers , dtype: int64
.iloc例子
>>> s.iloc[0]
11
>>> s.iloc[-1]
9
>>> s.iloc[4]
Traceback (most recent call last):
...
IndexError: single positional indexer is out-of-bounds
>>> s.iloc[0:3] # slice
1990 11
1993 9
Name: Magic Numbers , dtype: int64
>>> s.iloc[[0,1]] # list
1990 11
1993 9
Name: Magic Numbers , dtype: int64
.loc例子
>>> s.loc['1990']
11
>>> s.loc['1970']
Traceback (most recent call last):
...
KeyError: ’the label [1970] is not in the [index]’
>>> mask = s > 9
>>> s.loc[mask]
1990 11
Name: Magic Numbers , dtype: int64
>>> s.loc['1990':] # slice
1990 11
1993 9
Name: Magic Numbers, dtype: int64
因为s有字符串索引值,.loc将失败 用整数进行索引:
>>> s.loc[0]
Traceback (most recent call last):
...
KeyError: 0
下面的例子将说明其中的区别:
df = pd.DataFrame({'col1': [1,2,3,4,5], 'col2': ["foo", "bar", "baz", "foobar", "foobaz"]})
col1 col2
0 1 foo
1 2 bar
2 3 baz
3 4 foobar
4 5 foobaz
df = df.sort_values('col1', ascending = False)
col1 col2
4 5 foobaz
3 4 foobar
2 3 baz
1 2 bar
0 1 foo
基于索引的访问:
df.iloc[0, 0:2]
col1 5
col2 foobaz
Name: 4, dtype: object
我们得到排序后的数据框架的第一行。(这不是索引为0的行,而是索引为4的行)。
基于职位的访问:
df.loc[0, 'col1':'col2']
col1 1
col2 foo
Name: 0, dtype: object
我们得到下标为0的行,即使df已经排序。