【问题标题】:How to create the histogram of an array with masked values, in Numpy?如何在 Numpy 中创建具有掩码值的数组的直方图?
【发布时间】:2011-04-06 07:40:12
【问题描述】:

在 Numpy 1.4.1 中,计算 masked 数组的直方图最简单或最有效的方法是什么?默认情况下,numpy.histogrampyplot.hist 会计算被屏蔽的元素!

我现在能想到的唯一简单的解决方案是使用非屏蔽值创建一个新数组:

histogram(m_arr[~m_arr.mask])

但这不是很有效,因为这不必要地创建了一个新数组。我很乐意阅读更好的想法!

【问题讨论】:

  • 不管怎样,这可能会被认为是numpy.histogram 中的一个错误。您可能应该提交一份错误报告并在邮件列表中提及。通过将numpy.histogram 源中的asanyarray 替换为asarray,可以轻松解决此问题。
  • 乔,您可能想提交您的评论作为答案:如果 Numpy 开发人员确认,我可能会将其标记为已接受的答案。
  • 我向列表发送了一个快速问题。 mail.scipy.org/pipermail/numpy-discussion/2010-September/… 我们会看看人们是否认为它是一个错误。不过,这至少对我来说似乎违反直觉。
  • 对于它的价值,普遍的共识是它是预期的行为,并且这样的修复可能会导致比它修复的更多的问题。例如:mail.scipy.org/pipermail/numpy-discussion/2010-September/…
  • 谢谢你,乔。您能否在答案中总结您的 cmets。我想将其标记为已接受的答案,因为它表明没有什么比tillsten 的好解决方案更好的了。

标签: python arrays numpy histogram


【解决方案1】:

在尝试 Erik 的解决方案(请参阅 https://github.com/numpy/numpy/issues/16616)遇到强制转换问题后,我决定编写一个 numba 函数来实现此行为。

部分代码的灵感来自https://numba.pydata.org/numba-examples/examples/density_estimation/histogram/results.html。我添加了mask 位。

import numpy
import numba  

@numba.jit(nopython=True)
def compute_bin(x, bin_edges):
    # assuming uniform bins for now
    n = bin_edges.shape[0] - 1
    a_min = bin_edges[0]
    a_max = bin_edges[-1]

    # special case to mirror NumPy behavior for last bin
    if x == a_max:
        return n - 1  # a_max always in last bin

    bin = int(n * (x - a_min) / (a_max - a_min))

    if bin < 0 or bin >= n:
        return None
    else:
        return bin


@numba.jit(nopython=True)
def masked_histogram(img, bin_edges, mask):
    hist = numpy.zeros(len(bin_edges) - 1, dtype=numpy.intp)

    for i, value in enumerate(img.flat):
        if mask.flat[i]:
            bin = compute_bin(value, bin_edges)
            if bin is not None:
                hist[int(bin)] += 1
    return hist  # , bin_edges

加速非常显着。在 (1000, 1000) 图像上:

【讨论】:

    【解决方案2】:

    这是一个超级老问题,但这些天我只是使用:

    numpy.histogram(m_arr, bins=.., range=.., density=False, weights=m_arr_mask)

    其中 m_arr_mask 是一个与 m_arr 形状相同的数组,由要从直方图中排除的 m_arr 元素的 0 值和要包含的元素的 1 值组成。

    【讨论】:

    • 另外,如果您尝试为bins 传递字符串,这将不起作用。除此之外,答案很好。
    • 我似乎无法让它工作。当我为权重传递掩码数组时,结果似乎与没有掩码得到的结果不一致。我尝试传递一个随机 0 和 1 值的掩码,并期望每个 bin 中的计数除以大约 2。但它被除以 20 以上。
    • 我在一个更简单的例子(小得多的数组)上工作得很好。看起来像一个 numpy 错误,可能是权重导致 numpy.histogram 使用 uint8 数组作为输出,从而导致溢出。
    【解决方案3】:

    (根据上面的讨论取消删除...)

    我不确定 numpy 开发人员是否会认为这是一个错误或预期的行为。我asked on the mailing list,所以我想我们会看到他们说什么。

    不管怎样,这很容易解决。修补 numpy/lib/function_base.py 以在函数的输入上使用 numpy.asanyarray 而不是 numpy.asarray 将允许它正确使用掩码数组(或 ndarray 的任何其他子类)而无需创建副本。

    编辑:这似乎是预期的行为。 As discussed here:

    如果你想忽略屏蔽数据 只是在额外的函数调用中

    直方图(m_arr.compressed())

    我认为这不会使 额外的副本将是相关的, 因为我猜全蒙面数组 在直方图中处理将是 贵很多。

    使用 asanyarray 也将允许 和其他子类型中的矩阵 可能无法正确处理 直方图计算。

    除了掉落之外的任何其他事情 被掩盖的观察,这将是 有必要弄清楚是什么 直方图的掩码数组定义 正如布鲁斯所指出的那样。

    【讨论】:

    • 谢谢。反对在直方图中处理掩码数组的论点之一是,如果直方图处理掩码值,则必须决定如何处理带有掩码权重数组的掩码数据。我认为这个问题没有明显更好的解决方案:看起来histogram() 的功能与屏蔽输入+权重数组混合得不太好。
    【解决方案4】:

    试试hist(m_arr.compressed())

    【讨论】:

    • 这比我的m_arr[~m_arr.mask] 更好。但是,它并没有解决新数组被不必要地纠正的问题。
    猜你喜欢
    • 2019-09-29
    • 2017-12-07
    • 2017-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多