与 3d 数组的 numpy 分类比较

numpy classification comparison with 3d array

我正在尝试对 numpy 数组进行一些基本分类... 我想沿第 3 个维度将 2d 数组与 3d 数组进行比较,并根据相应的 z 轴值进行分类。

所以给定 3 个堆叠成 3d 数组的数组:

import numpy as np
a1 = np.array([[1,1,1],[1,1,1],[1,1,1]])
a2 = np.array([[3,3,3],[3,3,3],[3,3,3]])
a3 = np.array([[5,5,5],[5,5,5],[5,5,5]])
a3d = dstack((a1,a2,a3))

和另一个二维数组

a2d = np.array([[1,2,4],[5,5,2],[2,3,3]])

我希望能够比较 a2d 和 a3d,以及 return 最接近 a3d 级别的二维数组。 (或者我假设任何自定义函数可以比较沿 z 轴的每个值,并且 return 一个基于该比较的值。)

编辑

我修改了数组以更接近地匹配我的数据。 a1 是最小值,a2 是平均值,a3 是最大值。所以我想输出每个 a2d 值是否更接近 a1(分类为“1”)a2(分类为“2”)或 a3(分类为“3”)。我正在做一个 3d 数组,因为在真实数据中,它不会是一个简单的 3 数组选择,但出于 SO 目的,它有助于保持简单。我们可以假设在平局的情况下,我们将取较低的,因此 2 将被归类为“1”级,4 将被归类为“2”级。

您可以使用以下列表理解:

>>> [sum(sum(abs(i-j)) for i,j in z) for z in [zip(i,a2d) for i in a3d]]
[30.0, 22.5, 30.0]

在前面的代码中,我使用 zip 创建了以下列表,即 3d 列表的每个子数组的 zip 然后你需要的是计算这些对的减法元素的总和然后求和又是他们中的 :

>>> [zip(i,a2d) for i in a3d]
[[(array([ 1.,  3.,  1.]), array([1, 2, 1])), (array([ 2.,  2.,  1.]), array([5, 5, 4])), (array([ 3.,  1.,  1.]), array([9, 8, 8]))], [(array([ 4.,  6.,  4.]), array([1, 2, 1])), (array([ 5. ,  6.5,  4. ]), array([5, 5, 4])), (array([ 6.,  4.,  4.]), array([9, 8, 8]))], [(array([ 7.,  9.,  7.]), array([1, 2, 1])), (array([ 8.,  8.,  7.]), array([5, 5, 4])), (array([ 9.,  7.,  7.]), array([9, 8, 8]))]]

然后对于所有子数组,您将拥有以下列表:

[30.0, 22.5, 30.0]

每个子列表显示与二维数组的差异级别!然后您可以从 a3d 中获取相关子数组,如下所示:

>>> a3d[l.index(min(l))]
array([[ 4. ,  6. ,  4. ],
       [ 5. ,  6.5,  4. ],
       [ 6. ,  4. ,  4. ]])

也可以放在函数中:

>>> def find_nearest(sub,main):
...     l=[sum(sum(abs(i-j)) for i,j in z) for z in [zip(i,sub) for i in main]]
...     return main[l.index(min(l))]
... 
>>> find_nearest(a2d,a3d)
array([[ 4. ,  6. ,  4. ],
       [ 5. ,  6.5,  4. ],
       [ 6. ,  4. ,  4. ]])

您可以考虑使用 numpy.vectorize 的不同方法,它可以让您有效地将 python 函数应用于数组的每个元素。

在这种情况下,您的 python 函数可以根据您定义的任何中断对每个像素进行分类:

import numpy as np

a2d = np.array([[1,2,4],[5,5,2],[2,3,3]])
def classify(x):
    if x >= 4:
        return 3
    elif x >= 2:
        return 2
    elif x > 0:
        return 1
    else:
        return 0

vclassify = np.vectorize(classify)
result = vclassify(a2d)

感谢@perrygeo 和@Kasra - 他们让我朝着好的方向思考。 由于我想要对最接近的 3d 数组的 z 值进行分类,我无法进行简单的数学运算 - 我需要最接近值的 (z)index。

我通过枚举 2d 数组的两个轴,并对 3d 数组的相应 (z) 索引进行邻近比较来做到这一点。

可能有一种方法可以在不迭代 2d 数组的情况下执行此操作,但至少我避免了迭代 3d。

import numpy as np
a1 = np.array([[1,1,1],[1,1,1],[1,1,1]])
a2 = np.array([[3,3,3],[3,3,3],[3,3,3]])
a3 = np.array([[5,5,5],[5,5,5],[5,5,5]])
a3d = np.dstack((a1,a2,a3))

a2d = np.array([[1,2,4],[5,5,2],[2,3,3]])

classOut = np.empty_like(a2d)

def find_nearest_idx(array,value):
    idx = (np.abs(array-value)).argmin()
    return idx

# enumerate to get indices
for i,a in enumerate(a2d):
    for ii,v in enumerate(a):
        valStack = a3d[i,ii]
        nearest = find_nearest_idx(valStack,v)
        classOut[i,ii] = nearest

print classOut

这让我感动

[[0 0 1]
 [2 2 0]
 [0 1 1]]

这告诉我(例如)a2d[0,0] 最接近 a3d[0,0] 的 0 索引,在我的例子中意味着它最接近该 2d 位置的最小值. a2d[1,1] 最接近 2 索引,在我的例子中意味着更接近该 2d 位置的最大值。