Почему вы можете сделать df.loc(False) ['значение'] в pandas?

Я не вижу никакой документации по pandas, объясняя параметр False, переданный в loc. Может ли кто-нибудь объяснить, как() и [] отличаются в этом случае?

Ответы

Ответ 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__, который выполняет поиск/настройку.

Ответ 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 используется для нескольких дочерних классов.

Для метода .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. У меня есть dataframe формы (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, поскольку он используется в подклассе _IXIndexer. Однако: начиная с 0.20.0 индекс индекса .ix устарел, в пользу более строгих индексов .iloc и .loc. Аргумент передан вызов для .iloc и .loc игнорируется.

Ответ 3

Для любого объекта python () вызывает метод __call__, тогда как [] вызывает метод __getitem__ (если вы не устанавливаете значение, и в этом случае он вызывает __setitem__). Другими словами, () и [] вызывают разные методы, так почему вы ожидаете, что они будут действовать одинаково?