pandas sort_values throws ValueError:分类类别必须是唯一的

时间:2018-06-05 21:13:39

标签: python python-3.x pandas dataframe

我正在使用以下DataFrame架构:

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

其中co_Aco_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_xstr_x的某些组合可以正常运作,而其他组合则无效。


我认为这可能是混合类型的原因,所以我删除了字符串值并只留下自定义对象,错误仍然存​​在。我在这里一无所知,我将不胜感激。


编辑:我使用的是pandas版本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类是从lib导入的。

我所做的是我在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 :(得分:0)

这是一个古老的问题,但我遇到了同样的问题。

原因

问题在于,当两个对象相等时(由__hash__函数定义),您的True函数应始终返回__eq__

现在不是这种情况,因为您的等效项基于stream属性,并且您的类使用__hash__的{​​{1}}函数,(我相信)该函数基于对象在内存中的位置。

解决方案

按如下所示定义哈希函数可以解决问题。

object