为什么.loc具有切片的包容性行为?

时间:2018-04-22 04:10:31

标签: python pandas dataframe slice

出于某种原因,以下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约束被视为独占?

1 个答案:

答案 0 :(得分:2)

快速回答:

使用标签时进行包含端点的切片通常更有意义,因为它需要更少的关于DataFrame中其他行的知识。

每当你关心标签而不是位置时,最终排他标签切片会以一种不方便的方式引入位置依赖。

更长的回答:

任何功能的行为都是一种权衡:你偏爱某些用例而不是其他用例。最终,.iloc的操作是熊猫开发者的主观设计决策(正如@ALlollz的评论所指出的,这种行为is intentional)。但要理解为什么他们可能会这样设计它,想一想是什么让标签切片与位置切片不同。

想象一下,我们有两个DataFrame df1df2

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中获取bc之间的行。我们还想对df1df2使用相同的代码。由于bc在两个DataFrame中都没有相同的位置,因此简单的位置切片不会成功。所以我们转向基于标签的切片。

如果.loc是最终排他性,要在bc之间获取行,我们需要知道不仅是我们的标签期望的结束行,但也包括之后的下一行的标签。构建后,下一个标签在每个DataFrame中都会有所不同。

所以要么我们要么:

  • 为每个DataFrame使用单独的代码:df1.loc['b':'d']df2.loc['b':'z']。这很不方便,因为这意味着我们需要知道除了我们想要的行之外的额外信息。
  • 首先获取位置索引,添加1,然后使用位置切片: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]