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

Jam*_* Ko 11 python slice dataframe pandas

由于某些原因,以下两个调用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
Run Code Online (Sandbox Code Playgroud)

我了解这会loc考虑行标签,而会iloc考虑行的基于整数的索引。但是为什么loc呼叫的iloc上限被认为是包含的,而上限却被认为是排他的呢?

ASG*_*SGM 7

快速回答:

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

每当您关心标签而不是位置时,末端排他的标签切片都会以一种不方便的方式引入位置依赖性。


更长的答案:

任何功能的行为都是一个权衡:您偏爱某些用例。最终,.ilocPandas开发人员的操作是主观的设计决定(如@ALlollz的评论所示,此行为是故意的)。但是要了解为什么他们可能会这样设计,请考虑一下使标签切片与位置切片不同的原因。

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

df1 = pd.DataFrame(dict(X=range(4)), index=['a','b','c','d'])
df1 = pd.DataFrame(dict(X=range(4)), index=['b','c','z'])
Run Code Online (Sandbox Code Playgroud)

df1 包含:

   X
Y
a  0
b  1
c  2
d  3
Run Code Online (Sandbox Code Playgroud)

df2 包含:

   X
Y
b  0
c  1
z  2
Run Code Online (Sandbox Code Playgroud)

比方说,我们有一个基于标签的任务来执行:我们希望之间获得行bc来自df1df2,我们希望使用相同的代码两个DataFrames做到这一点。因为bc在两个DataFrame中都没有相同的位置,所以简单的位置切片无法解决问题。因此,我们转向基于标签的切片。

如果.loc是end-exclusive,则要在它们之间获得行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]。这只是罗word。

但是由于.loc包罗万象,所以我们只能说.loc['b':'c']。简单得多!

每当您关心标签而不是位置,并且尝试编写与位置无关的代码时,包含结尾的标签切片都会以一种不方便的方式重新引入位置相关性

就是说,也许在某些用例中,您确实希望基于标签的端排它切片。如果是这样,您可以在此问题中使用@Willz的答案

df.loc[start:end].iloc[:-1]
Run Code Online (Sandbox Code Playgroud)

  • @ASGM:因为标签切片是位置无关的。所以这句话可能会产生误导。 (2认同)
  • 在我看来,@Korchkidu 是对的。快速回答说:“每当您关心标签而不是位置时,最终独占标签切片都会以一种可能不方便的方式引入位置依赖性。” 我同意这一点。但在长答案中有一个不同的说法:“每当你关心标签而不是位置,并且你试图编写位置无关的代码时,结束包含标签切片会以一种不方便的方式重新引入位置依赖性”。哪里可能有拼写错误:“end-inclusive”应该替换为“end-exclusive”。暂时无法编辑。 (2认同)