【发布时间】:2018-01-25 23:21:05
【问题描述】:
我没有看到任何关于 pandas 的文档解释传递给 loc 的参数 False。谁能解释在这种情况下 () 和 [] 有何不同?
【问题讨论】:
我没有看到任何关于 pandas 的文档解释传递给 loc 的参数 False。谁能解释在这种情况下 () 和 [] 有何不同?
【问题讨论】:
df.loc 是_LocIndexer 类的一个实例,它恰好是_NDFrameIndexer 类的子类。
当您执行df.loc(...) 时,似乎调用了__call__ 方法,该方法无害地返回其自身的另一个实例。例如:
In [641]: df.loc
Out[641]: <pandas.core.indexing._LocIndexer at 0x10eb5f240>
In [642]: df.loc()()()()()()
Out[642]: <pandas.core.indexing._LocIndexer at 0x10eb5fe10>
...
等等。实例不以任何方式使用(...) 中传递的值。
另一方面,传递给[...] 的属性被发送到__getitem__/__setitem__,后者进行检索/设置。
【讨论】:
__setitem__分配。 OP 未指定。
df.loc,它确实被忽略了,但并非对于所有索引方法。
loc 方法将任何东西传递给__call__,因为它会被忽略并且根本不是预期的。 [] 是为了被使用,所以使用它。 () 不是,所以不要。
正如其他答案已经解释的那样,() 大括号调用 __call__ 方法,该方法定义为:
def __call__(self, axis=None):
# we need to return a copy of ourselves
new_self = self.__class__(self.obj, self.name)
new_self.axis = axis
return new_self
它返回一个自身的副本。现在,在() 之间传递的参数的作用是实例化新副本的axis 成员。因此,这可能会引发一个问题,即为什么作为参数传递的值并不重要,结果索引器完全相同。这个问题的答案在于超类_NDFrameIndexer 用于多个子类。
对于调用_LocIndexer 类的.loc 方法,此成员无关紧要。 LocIndexer 类本身是_LocationIndexer 的子类,_NDFrameIndexer 的子类。
每次axis 被_LocationIndexer 调用时,它默认为零,不可能自己指定。例如,我将引用该类中的一个函数,其他函数如下:
def __getitem__(self, key):
if type(key) is tuple:
key = tuple(com._apply_if_callable(x, self.obj) for x in key)
try:
if self._is_scalar_access(key):
return self._getitem_scalar(key)
except (KeyError, IndexError):
pass
return self._getitem_tuple(key)
else:
key = com._apply_if_callable(key, self.obj)
return self._getitem_axis(key, axis=0)
因此,无论您在.loc(whatever) 中传递什么参数,它都会被默认值覆盖。调用.iloc 时会看到类似的行为,它调用_iLocIndexer(_LocationIndexer),因此默认情况下也会覆盖此axis。
那么axis 在哪里发挥作用呢?答案是:在已弃用的.ix 方法中。我有一个形状为(2187, 5) 的数据框,现在定义:
a = df.ix(0)
b= df.ix(1)
c = df.ix(2)
a[0] == b[0] #True
b[0] == c[0] #True
a[0,1] == b[0,1] #False
如果您使用简单的标量索引,axis 在此二维示例中仍会被忽略,因为 get 方法会退回到简单的基于整数的标量索引。但是,a[0,1] 的形状为(2,5) axis=0 的前两个条目; b[0,1] 的形状为 (2187, 2) axis=1 的前两个条目; c[0,1] 返回ValueError: No axis named 2 for object type <class 'pandas.core.frame.DataFrame'>。
换句话说:
您仍然可以调用 _NDFrameIndexer 类的 call 方法,因为它在 _IXIndexer 子类中使用。但是:从 0.20.0 开始,不推荐使用 .ix 索引器,取而代之的是更严格的 .iloc 和 .loc 索引器。为 .iloc 和 .loc 传递给 call 的参数被忽略。
【讨论】:
对于任何 python 对象,() 调用__call__ 方法,而[] 调用__getitem__ 方法(除非您正在设置一个值,在这种情况下它调用__setitem__)。换句话说,() 和 [] 调用不同的方法,那么您为什么希望它们的行为相同呢?
【讨论】: