user308827
user308827

Reputation: 21971

Regrid numpy array based on cell area

import numpy as np
from skimage.measure import block_reduce

arr = np.random.random((6, 6))
area_cell = np.random.random((6, 6))

block_reduce(arr, block_size=(2, 2), func=np.ma.mean)

I would like to regrid a numpy array arr from 6 x 6 size to 3 x 3. Using the skimage function block_reduce for this.

However, block_reduce assumes each grid cell has same size. How can I solve this problem, when each grid cell has a different size? In this case size of each grid cell is given by the numpy array area_cell

-- EDIT:

An example:

arr

0.25    0.58    0.69    0.74
0.49    0.11    0.10    0.41
0.43    0.76    0.65    0.79
0.72    0.97    0.92    0.09

If all elements of area_cell were 1, and we were to convert 4 x 4 arr into 2 x 2, result would be:

0.36    0.48
0.72    0.61

However, if area_cell is as follows:

0.00    1.00    1.00    0.00
0.00    1.00    0.00    0.50
0.20    1.00    0.80    0.80
0.00    0.00    1.00    1.00

Then, result becomes:

0.17    0.22
0.21    0.54

Upvotes: 4

Views: 713

Answers (1)

Divakar
Divakar

Reputation: 221574

It seems you are still reducing by blocks, but after scaling arr with area_cell. So, you just need to perform element-wise multiplication between these two arrays and use the same block_reduce code on that product array, like so -

block_reduce(arr*area_cell, block_size=(2, 2), func=np.ma.mean)

Alternatively, we can simply use np.mean after reshaping to a 4D version of the product array, like so -

m,n = arr.shape
out = (arr*area_cell).reshape(m//2,2,n//2,2).mean(axis=(1,3))

Sample run -

In [21]: arr
Out[21]: 
array([[ 0.25,  0.58,  0.69,  0.74],
       [ 0.49,  0.11,  0.1 ,  0.41],
       [ 0.43,  0.76,  0.65,  0.79],
       [ 0.72,  0.97,  0.92,  0.09]])

In [22]: area_cell
Out[22]: 
array([[ 0. ,  1. ,  1. ,  0. ],
       [ 0. ,  1. ,  0. ,  0.5],
       [ 0.2,  1. ,  0.8,  0.8],
       [ 0. ,  0. ,  1. ,  1. ]])

In [23]: block_reduce(arr*area_cell, block_size=(2, 2), func=np.ma.mean)
Out[23]: 
array([[ 0.1725 ,  0.22375],
       [ 0.2115 ,  0.5405 ]])

In [24]: m,n = arr.shape

In [25]: (arr*area_cell).reshape(m//2,2,n//2,2).mean(axis=(1,3))
Out[25]: 
array([[ 0.1725 ,  0.22375],
       [ 0.2115 ,  0.5405 ]])

Upvotes: 2

Related Questions