【问题标题】:Why can you do df.loc(False)['value'] in pandas?为什么你可以在 pandas 中做 df.loc(False)['value']?
【发布时间】:2018-01-25 23:21:05
【问题描述】:

我没有看到任何关于 pandas 的文档解释传递给 loc 的参数 False。谁能解释在这种情况下 () 和 [] 有何不同?

【问题讨论】:

    标签: python pandas indexing


    【解决方案1】:

    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 未指定。
    • 一般情况下,.loc(...) 中可以包含哪些参数呢?
    • @user1559897 你可以传递任何你想要的,只要它是一个单一的参数,因为它被忽略了。
    • @COLDSPEED 对于df.loc,它确实被忽略了,但并非对于所有索引方法。
    • 最好不要通过loc 方法将任何东西传递给__call__,因为它会被忽略并且根本不是预期的。 [] 是为了被使用,所以使用它。 () 不是,所以不要。
    【解决方案2】:

    正如其他答案已经解释的那样,() 大括号调用 __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 &lt;class 'pandas.core.frame.DataFrame'&gt;

    换句话说:

    您仍然可以调用 _NDFrameIndexer 类的 call 方法,因为它在 _IXIndexer 子类中使用。但是:从 0.20.0 开始,不推荐使用 .ix 索引器,取而代之的是更严格的 .iloc 和 .loc 索引器。为 .iloc 和 .loc 传递给 call 的参数被忽略。

    【讨论】:

      【解决方案3】:

      对于任何 python 对象,() 调用__call__ 方法,而[] 调用__getitem__ 方法(除非您正在设置一个值,在这种情况下它调用__setitem__)。换句话说,()[] 调用不同的方法,那么您为什么希望它们的行为相同呢?

      【讨论】:

        猜你喜欢
        • 2021-03-18
        • 1970-01-01
        • 2012-11-17
        • 2020-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-07
        相关资源
        最近更新 更多