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

问题描述 投票:0回答:4

我是 numpy 的新手,我有一个 2D 对象数组,我需要将其装入一个较小的矩阵中,然后获取每个 bin 中对象的数量以制作热图。我按照这个线程上的答案创建了垃圾箱并对一个简单的数组进行了计数,但我不确定如何将其扩展到二维。这是我到目前为止所拥有的:

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]

 表示法将返回一个二进制值数组。我在任何地方都找不到有关此符号的文档。如有链接将不胜感激。

python numpy matrix scipy histogram2d
4个回答
14
投票
您可以将数组重塑为反映所需块结构的四维数组,然后沿每个块内的两个轴求和。 示例:

>>> 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
投票
另一个解决方案是查看此处注释中的

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)

结果将

data_matrix

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

希望这有帮助!


0
投票
这是我的功能:

def binning(im, binning_x, binning_y, mode='mean'): assert mode == ('sum' or 'mean') h, w = im.shape bins_x = h // binning_x bins_y = w // binning_y if mode == 'sum': binned_im = im[:bins_x*binning_x, bins_y*binning_y].reshape(bins_x, binning_x, bins_y, binning_y).sum(axis=(3,1)) else: binned_im = im[:bins_x*binning_x, bins_y*binning_y].reshape(bins_x, binning_x, bins_y, binning_y).mean(axis=(3,1)) return binned_im
    
© www.soinside.com 2019 - 2024. All rights reserved.