比较在python中包含nan的集合

时间:2014-11-08 02:33:38

标签: python set nan

我试图在python中比较包含nan的两个集合,但是因为{float('nan')} != {float('nan')}而努力这样做。例如:

s1 = {float('nan'), 1}
s2 = {float('nan'), 1, 2}

assert set.issubset(s1, s2)

我得到一个断言错误。我怎么处理这个?

3 个答案:

答案 0 :(得分:3)

一种方法:在相等之前测试身份(例如,请参阅文档中的here),因此如果您使用相同 nan,它就会起作用:< / p>

>>> nan = float("nan")
>>> s1 = {nan, 1}
>>> s2 = {nan, 1, 2}
>>> set.issubset(s1, s2)
True

即使

>>> s1 = {float("nan"), 1}
>>> s2 = {float("nan"), 1, 2}
>>> set.issubset(s1, s2)
False

使用nan非常尴尬,我会尽量避免将它们置于集合中并切换到不同的规范形式。但你可以随时确保它是同一个:

>>> def one_nan(x, nan=float("nan")):
...     return nan if math.isnan(x) else x
... 
>>> set.issubset(set(map(one_nan, s1)), set(map(one_nan, s2)))
True

或相同的千种变体。 (我有时会使用x != x作为纳米检测的捷径,但在这里明确表示可能是一个好主意。)

答案 1 :(得分:2)

创建删除了所有nan值的临时集,并将其进行比较。然后,分别处理nan比较。例如,您可以检查两个原始集是否都包含nan

即使您可以在没有断言异常的情况下对集合执行比较,float('nan') == float('nan')也会返回False,因此从此集合比较中获得的价值很小(它会使比较的其余部分无效) 。您可以通过打印set.issubset来检查此行为。

s1 = frozenset({float('nan'), 1})
s2 = frozenset({float('nan'), 1, 2})
print frozenset.issubset(s1,s2)

打印False

虽然set is deprecated,但您可以按如下方式生成临时集:

s3 = set([value for value in s1 if not math.isnan(value)])

(根据需要重复每个临时集)

答案 2 :(得分:2)

您也可以为此编写一个简单的函数。请注意,float('nan') == float('nan')的{​​{1}}为假;要检查是否有任何元素为nan,我们只需将其与自身进行比较。

nan

您可以简化def is_subset(s1, s2): no_nan_set = lambda s: {x for x in s if x == x} s1_nan, s2_nan = no_nan_set(s1), no_nan_set(s2) if s1_nan != s1 and s2_nan != s2: return s1_nan.issubset(s2_nan) elif s1_nan == s1 and s2_nan == s2: return s1.issubset(s2) else: return False

if-elif-else

请注意,如果您的任何一个集合中有两个或更多def is_subset(s1, s2): no_nan_set = lambda s: {x for x in s if x == x} s1_nan, s2_nan = no_nan_set(s1), no_nan_set(s2) return (s1_nan != s1 and s2_nan != s2 and s1_nan.issubset(s2_nan)) \ or (s1_nan == s1 and s2_nan == s2 and s1.issubset(s2)) s(因为nan),这将正常工作,同样如果float('nan') != float('nan')的{​​{1}} id是不同的。最后,即使你的一套或两套都没有nan,这也会有效。