【问题标题】:numpy classification comparison with 3d arraynumpy 与 3d 数组的分类比较
【发布时间】:2015-03-11 15:51:20
【问题描述】:

我正在尝试对 numpy 数组进行一些基本分类... 我想将 2d 数组与 3d 数组沿第 3 维进行比较,并根据相应的 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 进行比较,并返回最接近 a3d 级别的二维数组。 (或者我想任何自定义函数都可以比较沿 z 轴的每个值,并根据该比较返回一个值。)

编辑

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

【问题讨论】:

  • 当您将 a2d 与 a3d 进行比较时,您如何定义“最接近”?对于给定的函数 f(a2d, a23d),您期望返回是多少?
  • @perrygeo - 在一个特定情况下,我将拥有多年的 NDVI 数据。我将运行累积的最小、最大和平均栅格,它们代表一个像素级度量。我需要能够将任何单个 NDVI 与这些累积指标进行比较,并将每个像素分类为更接近最小值、最大值或平均值。因此,与三个指标中的每一个的数字接近度,最接近的一个定义了分类。在死分的情况下,我可能会选择平均值,但这种情况很少见,所以不会真的扭曲结果。

标签: python numpy multidimensional-array scipy


【解决方案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]

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

【讨论】:

  • 我喜欢这种方法。我正在为每个单独的值寻找一个分类,但这很酷!
  • @abenrob 你可以把它放在一个函数中!
  • @abenrob 查看编辑!如果你觉得这个答案有帮助,你可以通过投票和接受答案告诉社区;)
  • 我没有得到我期望的结果,所以我稍后会深入挖掘,我会回复你。
【解决方案2】:

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

【讨论】:

  • 这有利于根据数组本身的值进行分类,但我不知道如何使用它与其他 3d 数组中的值进行比较...
  • 基于我假设的示例,例如a1 表示在空间上没有变化的全局最小统计量,可以更有效地表示为标量值。如果这些在空间上有所不同,我的回答根本行不通。但它适用于标准的“分类”问题。
  • 是的 - 糟糕的虚假数据无济于事,是吗!
【解决方案3】:

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

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

可能有一种方法可以在不迭代 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-index,在我的情况下,这意味着更接近该 2d 位置的最大值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-12
    • 1970-01-01
    • 1970-01-01
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多