Почему логический оператор pandas не выравнивает индекс так, как должен?

Рассмотрим эту простую установку:

x = pd.Series([1, 2, 3], index=list('abc'))
y = pd.Series([2, 3, 3], index=list('bca'))

x

a    1
b    2
c    3
dtype: int64

y

b    2
c    3
a    3
dtype: int64

Как видите, индексы одинаковые, только в другом порядке.

Теперь рассмотрим простое логическое сравнение с использованием оператора равенства (==):

x == y
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)

Это выдает ValueError, скорее всего, потому что индексы не совпадают. С другой стороны, вызов эквивалентного оператора eq работает:

x.eq(y)

a    False
b     True
c     True
dtype: bool

OTOH, метод оператора работает, если y сначала переупорядочивается...

x == y.reindex_like(x)

a    False
b     True
c     True
dtype: bool

Насколько я понял, сравнение функций и операторов должно делать одно и то же, при прочих равных условиях. Что делает eq, чего не делает сравнение операторов?

Другая проблема, но только для подключения к сети: stackoverflow.com/questions/41410178/…

sanyassh 01.06.2019 11:13
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
26
1
1 440
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Что мне нравится в Python, так это то, что вы можете заглянуть в исходный код практически чего угодно. И из pd.Series.eq исходного кода он вызывает:

def flex_wrapper(self, other, level=None, fill_value=None, axis=0):
    # other stuff
    # ...

    if isinstance(other, ABCSeries):
        return self._binop(other, op, level=level, fill_value=fill_value)

и переходите к pd.Series._binop:

def _binop(self, other, func, level=None, fill_value=None):

    # other stuff
    # ...
    if not self.index.equals(other.index):
        this, other = self.align(other, level=level, join='outer',
                                 copy=False)
        new_index = this.index

Это означает, что оператор eq выравнивает два ряда перед сравнением (чего, по-видимому, не делает обычный оператор ==).

Вернемся к 2012 году, когда у нас нет eq, ne и gt, pandas есть проблема: беспорядок Series вернет неожиданный результат с логикой (>,<,==,!=), поэтому они делают это с исправлением (добавлена ​​новая функция, gt, ge, ne. .)

Билет GitHub ссылка

Ответ принят как подходящий

Просмотр всей трассировки для сравнения серии с несовпадающими индексами, особенно с акцентом на сообщение об исключении:

In [1]: import pandas as pd
In [2]: x = pd.Series([1, 2, 3], index=list('abc'))
In [3]: y = pd.Series([2, 3, 3], index=list('bca'))
In [4]: x == y
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-73b2790c1e5e> in <module>()
----> 1 x == y
/usr/lib/python3.7/site-packages/pandas/core/ops.py in wrapper(self, other, axis)
   1188 
   1189         elif isinstance(other, ABCSeries) and not self._indexed_same(othe
r):
-> 1190             raise ValueError("Can only compare identically-labeled "
   1191                              "Series objects")
   1192 
ValueError: Can only compare identically-labeled Series objects

мы видим, что это преднамеренное решение реализации. Кроме того, это не уникально для объектов Series — DataFrames вызывают аналогичную ошибку.

Копаясь в Git, обвиняя соответствующие строки, в конечном итоге обнаруживаются некоторые соответствующие коммиты и потоки отслеживания проблем. Например, Series.__eq__ раньше полностью игнорировал индекс RHS, и в комментарий в отчете об ошибке об этом поведении автор Pandas Уэс МакКинни говорит следующее:

This is actually a feature / deliberate choice and not a bug-- it's related to #652. Back in January I changed the comparison methods to do auto-alignment, but found that it led to a large amount of bugs / breakage for users and, in particular, many NumPy functions (which regularly do things like arr[1:] == arr[:-1]; example: np.unique) stopped working.

This gets back to the issue that Series isn't quite ndarray-like enough and should probably not be a subclass of ndarray.

So, I haven't got a good answer for you except for that; auto-alignment would be ideal but I don't think I can do it unless I make Series not a subclass of ndarray. I think this is probably a good idea but not likely to happen until 0.9 or 0.10 (several months down the road).

Тогда это было измененный для текущего поведения в pandas 0.19.0. Цитируя страница "что нового":

Following Series operators have been changed to make all operators consistent, including DataFrame (GH1134, GH4581, GH13538)

  • Series comparison operators now raise ValueError when index are different.
  • Series logical operators align both index of left and right hand side.

Это привело к тому, что поведение Series совпало с поведением DataFrame, который уже отклонял несоответствующие индексы при сравнении.

Таким образом, автоматическое выравнивание индексов операторами сравнения оказалось слишком сложным, так что это была лучшая альтернатива.

Отличный ответ. Должен быть значок следователя. Предназначен для таких ответов, когда автор ответа явно потратил время на исследование, чтение кода, копание в Git, чтобы найти логические объяснения. +1

Scott Boston 05.06.2019 15:32

Другие вопросы по теме