寻找两个Numpy数组的差异

3
我有两个数组,都来自文本文件。通过观察,它们看起来完全一样。但是当我测试这两个数组的等价性时,它们失败了 - 在元素、形状等方面都不同。我使用了numpy test,答案在这里回答。
这是两个矩阵
import numpy as np

class TextMatrixAssertions(object):
    def assertArrayEqual(self, dataX, dataY):
        x = np.loadtxt(dataX)
        y = np.loadtxt(dataY)

        if not np.array_equal(x, y):
            raise Exception("array_equal fail.")

        if not np.array_equiv(x, y):
            raise Exception("array_equiv fail.")

        if not np.allclose(x, y):
            raise Exception("allclose fail.")

dataX = "MyMatrix.txt"
dataY = "MyMatrix2.txt"
test = TextMatrixAssertions()
test.assertArrayEqual(dataX, dataY)

我想知道这两个数组是否真的有区别,如果没有,是什么导致了失败。


你可能会认为将值打印出来会使它们看起来相同?我建议尝试使用 print(repr(x))print(repr(y)),看看这是否能更清楚地显示这些值的差异。https://docs.python.org/3/library/functions.html#repr 试图打印“一个字符串,当传递给 eval() 时产生相同值的对象”。 - Patrick Fay
1
你意识到你的 raise 语句会中止方法的执行,对吧?因此,如果 array_equal() 返回 False,就永远不会执行 allclose() - Nils Werner
是的,我会添加注释来检查其他部分。 - Nikko
3个回答

8
它们不相等,它们有54个不同的元素。
np.sum(x!=y)

54

要找出哪些元素不同,您可以这样做:
np.where(x!=y)


(array([  1,   5,   7,  11,  19,  24,  32,  48,  82,  92,  97, 111, 114,
        119, 128, 137, 138, 146, 153, 154, 162, 165, 170, 186, 188, 204,
        215, 246, 256, 276, 294, 300, 305, 316, 318, 333, 360, 361, 390,
        419, 420, 421, 423, 428, 429, 429, 439, 448, 460, 465, 467, 471,
        474, 487]),
 array([18, 18, 18, 17, 17, 16, 15, 12,  8,  6,  5,  4,  3,  3,  2,  1,  1,
        26,  0, 25, 24, 24, 24, 23, 22, 20, 20, 17, 16, 14, 11, 11, 11, 10,
        10,  9,  7,  7,  5,  1,  1,  1, 26,  1,  0, 25, 23, 21, 19, 18, 18,
        17, 17, 14]))

你如何找到它们的索引? - Nikko

0

你应该先用一个更小、更简单的矩阵来测试你的函数。

例如:

import numpy as np
from io import StringIO



class TextMatrixAssertions(object):
    def assertArrayEqual(self, dataX, dataY):
        x = np.loadtxt(dataX)
        y = np.loadtxt(dataY)

        if not np.array_equal(x, y):
            raise Exception("array_equal fail.")

        if not np.array_equiv(x, y):
            raise Exception("array_equiv fail.")

        if not np.allclose(x, y):
            raise Exception("allclose fail.")

        return True

a = StringIO(u"0 1\n2 3")
b = StringIO(u"0 1\n2 3")
test = TextMatrixAssertions()
test.assertArrayEqual(a,b)

输出

True

所以我猜你的问题是出在文件上,而不是代码。你也可以尝试在x和y中加载相同的文件并查看输出。

要查看哪些元素不同,可以尝试使用not_equal

例子

a = StringIO(u"0 1\n2 3")
c = StringIO(u"0 1\n2 4")
x = np.loadtxt(a)
y = np.loadtxt(c)
np.not_equal(x,y)

Output

array([[False, False],
       [False,  True]])

是的,我知道函数没有问题,因为我在其他数组上测试过了。但是对于这些特定的矩阵,我就是看不出区别。 - Nikko
然后使用not_equal函数来查看哪些元素不同。 - NicoT

-1

另一种解决方案。您可以查看不相等的元素的值。如果运行以下代码,则会看到具有nan值的元素不相等,因此导致引发异常。

import numpy as np

class TextMatrixAssertions(object):
    def assertArrayEqual(self, dataX, dataY):
        x = np.loadtxt(dataX)
        y = np.loadtxt(dataY)

        if not np.array_equal(x, y):
            not_equal_idx = np.where(x != y)
            for idx1, idx2 in zip(not_equal_idx[0],not_equal_idx[1]):
                print(x[idx1][idx2])
                print(y[idx1][idx2])
            raise Exception("array_equal fail.")

        if not np.array_equiv(x, y):
            raise Exception("array_equiv fail.")

        if not np.allclose(x, y):
            raise Exception("allclose fail.")

dataX = "MyMatrix.txt"
dataY = "MyMatrix2.txt"
test = TextMatrixAssertions()
test.assertArrayEqual(dataX, dataY)

输出:

nan
nan
nan
...
nan

这太过复杂了。 - Nils Werner
我不明白你的意思。也许你是指当输入文件为空或长度不同时的一些特殊情况。然而,对于 OP 提供的输入和为了向他解释代码为什么会引发异常的目的,我的代码已经完成了任务。 - eugen
是的,这只是不必要地复杂 :-) idx = x != y; print(x[idx], y[idx]) 做同样的事情,但更简单和更快。 - Nils Werner
那么 idx = x != y; print(x[idx], y[idx]) 如何解决你所说的“意外后果”?你能详细说明一下吗? - eugen
在编程中,当你应该始终使用x[i, j]时,它使用了x[i][j] - Nils Werner
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接