DataFrame的iloc,ix和loc这三种切片方法有何不同吗?
之前看过一些官方文档,但还是无法理解这三者之间的区别。
例如,假设我们要获取DataFrame
的前五行。这三者内部是如何实现的?求解释!
df.loc[:5]
df.ix[:5]
df.iloc[:5]
最佳回答
iloc
基于整数定位。因此,无论您的行标签是什么,您始终可以例如通过执行以下操作获得第一行
df.iloc[0]
或最后五行
df.iloc[-5:]
您也可以在列上使用它。这将检索第三列:
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
使用命名索引。给定一个带有字符串作为行和列标签的DataFrame:
df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name'])
然后我们可以得到第一行
df.loc['a'] # equivalent to df.iloc[0]
和'date'
列的后两行
df.loc['b':, 'date'] # equivalent to df.iloc[1:, 1]
可能值得指出的是,DataFrame
的默认行和列索引是从0开始的整数。如果您有非数字索引,例如字符串或日期时间,则df.loc[:5]
会引发错误。
另外,您可以使用DataFrame的__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
的第一行和第三行。这等效于df[b]
进行选择,但也可以用于通过布尔向量进行内容设置:
df.loc[b, 'name'] = 'Mary', 'John'
次佳回答
.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'])
所有粗体字均为标签。列使用标签age
,color
,food
,height
,score
和state
列。索引使用的是标签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 在返回值中包含停止值。以下是从Aaron(亚伦)到Dean(迪恩(含))的片段。它的步长未明确定义,但默认为1。
df.loc['Aaron':'Dean']
可以采用与Python列表相同的方式获取复杂的切片。
.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]]
这将返回第三行和倒数第二行的DataFrame:
使用带切片符号的.iloc选择多行
df.iloc[:5:3] # 从第0行开始到第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岁以上的所有行,并仅返回food
和score
列,则可以执行以下操作:
df.loc[df['age'] > 30, ['food', 'score']]
您可以使用.iloc实现类似的功能
,但不能将其传递为布尔Series(系列),而必须将boolean Series转换为numpy数组,如下所示:
df.iloc[(df['age'] > 30).values, [2, 4]]
选择所有行[即做列选择]
可以将.loc和.iloc
用于仅列选择。您可以使用如下冒号来选择所有行:
df.loc[:, 'color':'score':2]
索引运算符[]
也可以选择行和列,但不能同时选择。
大多数人都熟悉DataFrame索引运算符的主要目的,即选择列。字符串选择单个列作为系列,而字符串列表选择多个列作为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,第3个数字是步长
注意:单独的索引运算符无法同时选择行和列。
df[3:5, 'color']
TypeError: unhashable type: 'slice'
参考资料