如何在numpy中对2D数组进行分箱操作?

9

我对numpy不熟悉,我有一个二维对象数组需要分成更小的矩阵并计算每个矩阵中对象数量以制作热图。我按照此线程的答案创建了简单数组的分组和计数,但不知道如何扩展到二维。以下是我目前的代码:

data_matrix = numpy.ndarray((500,500),dtype=float)
# fill array with values.

bins = numpy.linspace(0,50,50)
digitized = numpy.digitize(data_matrix, bins)

binned_data = numpy.ndarray((50,50))
for i in range(0,len(bins)):
    for j in range(0,len(bins)):
        k = len(data_matrix[digitized == i:digitized == j]) # <-not does not work
        binned_data[i:j] = k

附注:在数组上使用[digitized == i]表示法将返回一个二进制值的数组。我无法在任何地方找到关于这个符号的文档,如果有链接将不胜感激。


3
能否给出一个3x3的数组或相似的简单例子?我不理解你的目的。我不确定,也许你想看看 np.histogram2d 函数? - Syrtis Major
1
请查看此链接:https://scipython.com/blog/binning-a-2d-array-in-numpy/ - Yonatan Simson
3个回答

13

您可以将数组重塑为反映所需块结构的四维数组,然后在每个块内沿着两个轴求和。例如:

>>> a = np.arange(24).reshape(4, 6)
>>> a
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])
>>> a.reshape(2, 2, 2, 3).sum(3).sum(1)
array([[ 24,  42],
       [ 96, 114]])

如果a的形状为m, n,则重塑后的形状应为

a.reshape(m_bins, m // m_bins, n_bins, n // n_bins)

2
起初,我也建议您使用np.histogram2d而不是重新发明轮子,但后来意识到这样做会过度使用并且仍需要一些修改。如果我理解正确,您只想对输入的子矩阵求和。这很容易强制执行:遍历输出子矩阵并总结每个输入子块。
import numpy as np

def submatsum(data,n,m):
    # return a matrix of shape (n,m)
    bs = data.shape[0]//n,data.shape[1]//m  # blocksize averaged over
    return np.reshape(np.array([np.sum(data[k1*bs[0]:(k1+1)*bs[0],k2*bs[1]:(k2+1)*bs[1]]) for k1 in range(n) for k2 in range(m)]),(n,m))

# set up dummy data
N,M = 4,6
data_matrix = np.reshape(np.arange(N*M),(N,M))

# set up size of 2x3-reduced matrix, assume congruity
n,m = N//2,M//3
reduced_matrix = submatsum(data_matrix,n,m)

# check output
print(data_matrix)
print(reduced_matrix)

这将打印输出

print(data_matrix)
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]
 [18 19 20 21 22 23]]

print(reduced_matrix)
[[ 24  42]
 [ 96 114]]

这实际上是将形状为 (2,3) 的子矩阵相加的结果。

请注意,我使用//进行整数除法以确保与Python3兼容,但在Python2中,您可以直接使用/进行除法运算(因为所涉及的数字是整数)。


1
如果每个轴上的箱子数量是相应轴上维度的除数,则可以在不使用任何Python循环的情况下执行此操作(速度更快)。诀窍是将数组重新塑造为四维数组,然后沿正确的轴进行求和。 - Sven Marnach
@SvenMarnach 你说得对,我总是忘记那个技巧 :) 你想把它加入回答中吗? - Andras Deak -- Слава Україні
昨天我没有时间发布答案,所以希望其他人可以做。 - Sven Marnach

1
另一种解决方案是查看此处评论中的binArray函数: 将numpy数组分组 使用您的示例:
data_matrix = numpy.ndarray((500,500),dtype=float)
binned_data = binArray(data_matrix, 0, 10, 10, np.sum)
binned_data = binArray(binned_data, 1, 10, 10, np.sum)

将大小为10x10的所有正方形在data_matrix中求和(大小为500x500),以获得每个正方形在binned_data中的单个值(大小为50x50)。

希望这可以帮到您!


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