Python pandas sort_值抛出ValueError:分类类别必须唯一
我有以下Python pandas sort_值抛出ValueError:分类类别必须唯一,python,python-3.x,pandas,dataframe,Python,Python 3.x,Pandas,Dataframe,我有以下DataFrameschema: |str|u A | str|B | co|u A | co|u B |……|一氧化碳| 其中co_A和co_B代表自定义对象 这些对象继承了对象,并定义了丰富的比较方法 FWIW:\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu 我想做的是按两个自定义列进行排序,这就是混淆的地方 以下代码按预期工作: df.so
DataFrame
schema:
|str|u A | str|B | co|u A | co|u B |……|一氧化碳|
其中co_A
和co_B
代表自定义对象
这些对象继承了
对象
,并定义了丰富的比较方法
FWIW:\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
我想做的是按两个自定义列进行排序,这就是混淆的地方
以下代码按预期工作:
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
的某些组合确实有效,而其他组合则无效
我认为这可能是混合类型的原因,所以我删除了字符串值,只留下自定义对象,错误仍然存在。我在这里一无所知,我将感谢任何帮助
编辑:我正在使用熊猫版本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类肯定有问题(我没有编写该类,但是,我找不到任何可能导致该问题的内容)
该类应该处理版本比较——可以在gist中找到规范
EDIT3:找到了问题的根本原因,但不知道如何解决
已经实现了自定义对象
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__()
类自定义对象:
定义初始化(自,流:str):
如果流为“无”:
raise TypeError()
self.stream=流
定义报告(自我):
返回“{cls!s}(stream={stream!r})”(
cls=self.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,
stream=self.stream
)
定义(自我):
返回“{stream!s}”。格式(
stream=self.stream
)
定义(自身、其他):
如果“其他”为“无”:
返回错误
返回self.streamother.stream
#这是个老问题,但我遇到了同样的问题
原因
问题在于,当两个对象相等时(由\uuuuuu eq\uuuu
函数定义),您的\uuuuuuu散列\uuuu
函数应始终返回True
现在情况并非如此,因为您的等价性是基于流
属性的,并且您的类使用对象
的散列
函数,它(我相信)基于对象在内存中的位置
解决方案
按照下面的方式定义散列函数可能会达到这个目的
def __hash__(self):
return hash(self.stream)
你在使用熊猫0.23.0吗?你能提供一些数据来说明这个问题吗?在我的问题中添加了这些信息,谢谢你的注释。谢谢你的评论!我以为它已经死了。。是的,我很难找到答案。我假设可以将等价性与哈希函数分开定义。也就是说,哈希值可能不相等,但对象将通过=
符号比较相等值。这显然是错误的假设。比较相等的可散列对象必须具有相同的散列值。这里的问题是,哈希在对象生存期内不能更改,而stream
属性也不能更改,所以我无法使用您的解决方案。