pandas sort_values ​​выдает ValueError: Категориальные категории должны быть уникальными - PullRequest
0 голосов
/ 06 июня 2018

У меня следующая схема DataFrame:

|str_A |str_B |co_A |co_B |... |co_X |

, где co_A и co_B обозначают пользовательских объектов


Эти объекты наследуют object и имеют определенныебогатые методы сравнения

FWIW: __hash__ метод также переопределяется и вызывает super().__hash__()


Что я хочу сделать, это отсортировать по двум пользовательскимстолбцы, и вот где возникает путаница.

Следующий код работает должным образом:

df.sort_values(by=['str_A', 'str_B'])

Также работает следующий код:

df.sort_values(by=['co_A'])


, но не работает:

df.sort_values(by=['co_A', 'co_B'])

, который выдает

ValueError: Категориальные категории должны быть уникальными

И получается, что некоторые комбинации co_x и str_x работают, другие нет.


Я подумал, что это может быть причиной смешанных типов, и поэтому я отбросилСтроковые значения и оставили только пользовательские объекты, ошибка сохраняется.Я ничего не понимаю здесь, и я был бы признателен за любую помощь.


EDIT : Я использую панды версии 0.23.0

для генерацииПростые данные, с которыми я могу воспроизвести проблему, можно использовать следующий пример кода

def feed():
    return type('Feed', (), {
        attr: names.get_first_name() if attr.startswith('substr') else names.get_last_name()
        for attr in CPE_VERSION_ATTRIBUTE_LIST
    })

feed = [feed() for i in range(100)]

EDIT2 :

Я использую ноутбук Jupyter, CustomObject класс импортирован из библиотеки.

Я создал еще один простой класс непосредственно в jupyter, используя методы, аналогичные оригинальным, чтобы проверить, что с данными что-то не так ... и это сработало.Что еще более запутанно.Должно быть что-то не так с классом CustomObject (я не писал этот класс, однако не могу найти ничего, что могло бы вызвать проблему).

Класс должен обрабатывать сравнения версий -Спецификация может быть найдена в сущности https://gist.github.com/CermakM/011f17e91ffe9efbe35f29738fb23ec2

EDIT3 : найдена основная причина проблемы, пока не знаю, как ее решить,

Имеяреализован CustomObject как

class CustomObject:

    def __init__(self, stream: str):
        if stream is None:
            raise TypeError()

        self.stream = stream

    def __repr__(self):
        return "{cls!s}(stream={stream!r})".format(
            cls=self.__class__.__name__,
            stream=self.stream
        )

    def __str__(self):
        return "{stream!s}".format(
            stream=self.stream
        )

    def __lt__(self, other):
        if other is None:
            return False

        return self.stream < other.stream

    def __gt__(self, other):
        if other is None:
            return True

        return self.stream > other.stream

    # <<<<<<< This causes the issue 
    #     def __eq__(self, other):
    #         if other is None:
    #             return False

    #         return self.stream == other.stream
    # =======

    def __hash__(self):
        return super().__hash__()

Работает, как и ожидалось, без комментированного кода выше.

1 Ответ

0 голосов
/ 26 июля 2018

Это старый вопрос, но я столкнулся с той же проблемой.

Причина

Проблема в том, что ваша функция __hash__ всегда должна возвращать True, когда два объекта являютсяравно (как определено вашей __eq__ функцией).

Сейчас это не так, потому что ваша эквивалентность основана на атрибуте stream, а ваш класс использует __hash__ функцию object, которая (я полагаю) основана на расположении объектов в памяти.

Решение

Определение хеш-функции, как показано ниже, может помочь.

def __hash__(self):
    return hash(self.stream)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...