与3d数组的numpy分类比较

时间:2015-03-11 15:51:21

标签: python numpy multidimensional-array scipy

我正在尝试对numpy数组进行一些基本分类...... 我想比较一个二维数组和一个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))

和另一个2d数组

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

我希望能够将a2d与a3d进行比较,并返回a3d最接近的2d数组。 (或者我想任何可以比较沿z轴的每个值的自定义函数,并根据该比较返回一个值。)

修改

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

3 个答案:

答案 0 :(得分:1)

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

>>> [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]

对于每个子列表显示与2d数组的差异级别!然后您可以从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. ]])

答案 1 :(得分:1)

您可以考虑使用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)

答案 2 :(得分:0)

感谢@perrygeo和@Kasra--他们让我思考方向。 因为我想要对最接近的3d数组的z值进行分类,所以我不能做简单的数学运算 - 我需要最接近值的(z)索引。

我是通过枚举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位置的最大值。