出于某种原因,以下2次调用iloc
/ loc
会产生不同的行为:
>>> import pandas as pd
>>> df = pd.DataFrame(dict(A=range(3), B=range(3)))
>>> df.iloc[:1]
A B
0 0 0
>>> df.loc[:1]
A B
0 0 0
1 1 1
我理解loc
考虑行标签,而iloc
考虑行的基于整数的索引。但为什么loc
调用的上限被认为是包容性的,而iloc
约束被视为独占?
答案 0 :(得分:2)
快速回答:
使用标签时进行包含端点的切片通常更有意义,因为它需要更少的关于DataFrame中其他行的知识。
每当你关心标签而不是位置时,最终排他标签切片会以一种不方便的方式引入位置依赖。
更长的回答:
任何功能的行为都是一种权衡:你偏爱某些用例而不是其他用例。最终,.iloc
的操作是熊猫开发者的主观设计决策(正如@ALlollz的评论所指出的,这种行为is intentional)。但要理解为什么他们可能会这样设计它,想一想是什么让标签切片与位置切片不同。
想象一下,我们有两个DataFrame df1
和df2
:
df1 = pd.DataFrame(dict(X=range(4)), index=['a','b','c','d'])
df1 = pd.DataFrame(dict(X=range(4)), index=['b','c','z'])
df1
包含:
X
Y
a 0
b 1
c 2
d 3
df2
包含:
X
Y
b 0
c 1
z 2
我们假设我们要执行基于标签的任务:我们希望从两个DataFrame中获取b
和c
之间的行。我们还想对df1
和df2
使用相同的代码。由于b
和c
在两个DataFrame中都没有相同的位置,因此简单的位置切片不会成功。所以我们转向基于标签的切片。
如果.loc
是最终排他性,要在b
和c
之间获取行,我们需要知道不仅是我们的标签期望的结束行,但也包括之后的下一行的标签。构建后,下一个标签在每个DataFrame中都会有所不同。
所以要么我们要么:
df1.loc['b':'d']
和df2.loc['b':'z']
。这很不方便,因为这意味着我们需要知道除了我们想要的行之外的额外信息。df.loc[df.index.get_loc('b'):df.index.get_loc('c')+1]
。这只是罗嗦。 但由于.loc
是包含端点的,我们可以说.loc['b':'c']
。更简单!
每当您关心标签而不是位置,并且您尝试编写与位置无关的代码时,包含端点的标签切片会以一种不方便的方式重新引入位置依赖性
也就是说,也许有些用例确实需要基于标签的终端专有切片。如果是这样,您可以使用@Willz's answer in this question:
df.loc[start:end].iloc[:-1]