如何测试两个 pandas 分类系列是否仅在类别标签上有所不同
How to test if two pandas categorical Series differ only by the category labels
假设我有两个分类 pandas.Series
像这样:
> series_1 = pandas.Categorical(
["A", "B", "C", "A", "C"],
categories=["A", "B", "C"]
)
> series_2 = pandas.Categorical(
[1, 2, 3, 1, 3],
categories=[1, 3, 2]
)
因此,这两个系列的信息内容完全相同,只是类别的标记方式不同。我的目标是非常快速地对此进行测试,因为我有一个包含数百个此类列的数据框。
到目前为止我所做的是用 pandas.crosstab
计算偶然性 table 并检查它是否是对角矩阵(np.diag(cont_table).sum() == cont_table.sum()
,这并不完美)。
我可以简单地将标签转换为整数,并始终使用第一次出现的顺序来保证相应的标签将分配给相同的整数,但我觉得这是一个如此基本的任务,肯定 pandas 已经有一些方法可以做到这一点。
因此问题是:是否有一种快速、简单的方法来通过几次调用 pandas 方法来进行此检查?
编辑:
已更改为更清楚地展示任务难度的不同示例,因为某些答案适用于上一个示例,但不能解决一般问题。请注意,我通常不能相信这两个系列中的类别会按照相应标签的相同顺序正确配对。
在 this gist 中有一个代码可以生成此问题的随机实例以测试最终的解决方案。代码很简单:
- 生成两个结构相同但标签不同的numpy数组
- labels 创建两个系列并调用
.astype('category')
方法。
它经常会产生类别不正确的情况。
如果您确信类别的顺序相同(如本例所示),您可以这样做:
series_match = (series_1 == series_2).all()
// True for this example
好吧,我在文档上苦苦思索了一会儿,结果证明我可以做到这一点:
import pandas as pd
def compare_categorical_series():
values_1, *_ = pd.factorize(feature_1)
values_2, *_ = pd.factorize(feature_2)
return np.all(values_1 == values_2)
factorize
函数将每个条目转换为一个整数值,使用相同的整数表示相等。当然,这还不够,还需要始终以相同的顺序执行此操作,而不管实际标签是什么。
尽管未在 pandas 文档中按原样记录 这种行为,但经过大量测试后,似乎确实是这种行为。似乎整数是按照标签在系列中出现的顺序分配的,这足以保证此应用程序所需的行为。
但是由于没有记录此行为,它将来可能会发生变化,因此最好有适当的测试用例来检测可能的行为变化。
假设我有两个分类 pandas.Series
像这样:
> series_1 = pandas.Categorical(
["A", "B", "C", "A", "C"],
categories=["A", "B", "C"]
)
> series_2 = pandas.Categorical(
[1, 2, 3, 1, 3],
categories=[1, 3, 2]
)
因此,这两个系列的信息内容完全相同,只是类别的标记方式不同。我的目标是非常快速地对此进行测试,因为我有一个包含数百个此类列的数据框。
到目前为止我所做的是用 pandas.crosstab
计算偶然性 table 并检查它是否是对角矩阵(np.diag(cont_table).sum() == cont_table.sum()
,这并不完美)。
我可以简单地将标签转换为整数,并始终使用第一次出现的顺序来保证相应的标签将分配给相同的整数,但我觉得这是一个如此基本的任务,肯定 pandas 已经有一些方法可以做到这一点。
因此问题是:是否有一种快速、简单的方法来通过几次调用 pandas 方法来进行此检查?
编辑:
已更改为更清楚地展示任务难度的不同示例,因为某些答案适用于上一个示例,但不能解决一般问题。请注意,我通常不能相信这两个系列中的类别会按照相应标签的相同顺序正确配对。
在 this gist 中有一个代码可以生成此问题的随机实例以测试最终的解决方案。代码很简单:
- 生成两个结构相同但标签不同的numpy数组
- labels 创建两个系列并调用
.astype('category')
方法。
它经常会产生类别不正确的情况。
如果您确信类别的顺序相同(如本例所示),您可以这样做:
series_match = (series_1 == series_2).all()
// True for this example
好吧,我在文档上苦苦思索了一会儿,结果证明我可以做到这一点:
import pandas as pd
def compare_categorical_series():
values_1, *_ = pd.factorize(feature_1)
values_2, *_ = pd.factorize(feature_2)
return np.all(values_1 == values_2)
factorize
函数将每个条目转换为一个整数值,使用相同的整数表示相等。当然,这还不够,还需要始终以相同的顺序执行此操作,而不管实际标签是什么。
尽管未在 pandas 文档中按原样记录 这种行为,但经过大量测试后,似乎确实是这种行为。似乎整数是按照标签在系列中出现的顺序分配的,这足以保证此应用程序所需的行为。
但是由于没有记录此行为,它将来可能会发生变化,因此最好有适当的测试用例来检测可能的行为变化。