为什么你能在熊猫中做df.loc(假)['价值']?

时间:2017-08-17 13:45:50

标签: python pandas indexing

我没有看到任何关于pandas的文档,解释传递给loc的参数False。任何人都可以解释这种情况下()和[]的不同之处吗?

3 个答案:

答案 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__()会调用不同的方法,那么为什么你会期望它们的行为相同?