Для ясности я извлечу отрывок из моего кода и использую общие имена. У меня есть класс Foo()
, который хранит DataFrame для атрибута.Как перегружать `__eq__` для сравнения pandas DataFrames и Series?
import pandas as pd
import pandas.util.testing as pdt
class Foo():
def __init__(self, bar):
self.bar = bar # dict of dicts
self.df = pd.DataFrame(bar) # pandas object
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.__dict__ == other.__dict__
return NotImplemented
def __ne__(self, other):
result = self.__eq__(other)
if result is NotImplemented:
return result
return not result
Однако, когда я пытаюсь сравнить два экземпляра из Foo
, я получаю excepetion, связанные с неоднозначностью сравнения двух DataFrames (сравнение должно работать нормально без ключа «» в ф.р. Foo.__dict__
).
d1 = {'A' : pd.Series([1, 2], index=['a', 'b']),
'B' : pd.Series([1, 2], index=['a', 'b'])}
d2 = d1.copy()
foo1 = Foo(d1)
foo2 = Foo(d2)
foo1.bar # dict
foo1.df # pandas DataFrame
foo1 == foo2 # ValueError
[Out] ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
К счастью, у pandas есть служебные функции для утверждения, являются ли два DataFrames или Series истинными. Я хотел бы использовать операцию сравнения этой функции, если это возможно.
pdt.assert_frame_equal(pd.DataFrame(d1), pd.DataFrame(d2)) # no raises
Есть несколько вариантов, чтобы решить сравнение двух Foo
экземпляров:
- сравнить копию
__dict__
, гдеnew_dict
не хватает ФР ключа - удалить ключ ф.р. из
__dict__
(не идеально) - не сравнить
__dict__
, но только его части, содержащиеся в кортеже - перегружать
__eq__
для облегчения панды DataFrame сравнения
Последний вариант кажется самым надежным в долгосрочной перспективе, но я не уверен, что лучший подход. В конце концов, Я хотел был бы refactor __eq__
, чтобы сравнить все элементы от Foo.__dict__
, включая DataFrames (и Series). Любые идеи о том, как это сделать?
Почему вы просто не делаете подклассы для dataframe и series и не создаете собственную функцию '__eq__'? Вы можете супер оригинал для других случаев. – postelrich