我没有看到任何关于pandas的文档,解释传递给loc的参数False。任何人都可以解释这种情况下()和[]的不同之处吗?
答案 0 :(得分:12)
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__
。
答案 1 :(得分:5)
正如其他答案已经解释的那样,()
大括号调用__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
用于多个子类。
对于调用.loc
类的_LocIndexer
方法,此成员无关紧要。 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)
&lt; - 它需要axis=0
的前两个条目; b[0,1]
形状为(2187, 2)
&lt; - 它需要axis=1
的前两个条目; c[0,1]
会返回ValueError: No axis named 2 for object type <class 'pandas.core.frame.DataFrame'>
。
换句话说:
您仍然可以调用_NDFrameIndexer类的调用方法,因为它在_IXIndexer子类中使用。但是:从0.20.0开始,不推荐使用.ix索引器,而使用更严格的.iloc和.loc索引器。传递给.iloc和.loc的调用的参数将被忽略。
答案 2 :(得分:2)
对于任何python对象,()
调用__call__
方法,而[]
调用__getitem__
方法(除非你设置一个值,在这种情况下它会调用{ {1}})。换句话说,__setitem__
和()
会调用不同的方法,那么为什么你会期望它们的行为相同?