Blockwise sum of matrix elements
You can use matrix multiplication for this.
# Computation matrix:
mat <- function(n, r) {
suppressWarnings(matrix(c(rep(1, r), rep(0, n)), n, n/r))
}
Square-matrix example, uses a matrix and its transpose on each side of a
:
# Reduce a 4x4 matrix by a factor of 2:
x <- mat(4, 2)
x
## [,1] [,2]
## [1,] 1 0
## [2,] 1 0
## [3,] 0 1
## [4,] 0 1
t(x) %*% a %*% x
## [,1] [,2]
## [1,] 12 15
## [2,] 10 16
Non-square example:
b <- matrix(1:24, 4 ,6)
t(mat(4, 2)) %*% b %*% mat(6, 2)
## [,1] [,2] [,3]
## [1,] 14 46 78
## [2,] 22 54 86
Sum over blocks in a 2D matrix - MATLAB
An alternative way is to reshape the whole matrix into a 4D matrix and sum the elements over first and third dimension:
result = squeeze(sum(sum(reshape(A,26,189,26,189),1),3));
tensorflow: block-wise array/matrix sums
You can do it using tf.reshape
and tf.reduce_sum
as follows:
import tensorflow as tf
n=tf.constant([1,2,3,4,5,6])
res=tf.reduce_sum(tf.reshape(n,(3,2)),1)
sess=tf.Session()
res.eval(session=sess)
This prints array([ 3, 7, 11])
In the general case, if you want to get the sums of disjoint sequences of k
elements, replace tf.reshape(n,(3,2))
with tf.reshape(n,(-1,k))
. (The -1 will force it to specify the number of rows to n/k
).
How to evaluate the sum of values within array blocks
Simply reshape
splitting each of those two axes into two each with shape (5,20)
to form a 4D
array and then sum reduce along the axes having the lengths 20
, like so -
Z_new = Z.reshape(5,20,5,20).sum(axis=(1,3))
Functionally the same, but potentially faster option with np.einsum
-
Z_new = np.einsum('ijkl->ik',Z.reshape(5,20,5,20))
Generic block size
Extending to a generic case -
H,W = 5,5 # block-size
m,n = Z.shape
Z_new = Z.reshape(H,m//H,W,n//W).sum(axis=(1,3))
With einsum
that becomes -
Z_new = np.einsum('ijkl->ik',Z.reshape(H,m//H,W,n//W))
To compute average/mean across blocks, use mean
instead of sum
method.
Generic block size and reduction operation
Extending to use reduction
operations that have ufuncs
supporting multiple axes
parameter with axis
for reductions, it would be -
def blockwise_reduction(a, height, width, reduction_func=np.sum):
m,n = a.shape
a4D = a.reshape(height,m//height,width,n//width)
return reduction_func(a4D,axis=(1,3))
Thus, to solve our specific case, it would be :
blockwise_reduction(Z, height=5, width=5)
and for a block-wise average computation, it would be -
blockwise_reduction(Z, height=5, width=5, reduction_func=np.mean)
How to dynamically reshape matrix block-wise?
Here's a vectorized approach with reshape
and permute
-
reshape(permute(reshape(a,size(a,1),4,[]),[1,3,2]),[],4)
Making it generic, we could introduce the number of columns as a parameter. Hence, let ncols
be that one. So, the solution becomes -
ncols = 4
reshape(permute(reshape(a,size(a,1),ncols,[]),[1,3,2]),[],ncols)
Sample run -
>> a
a =
20 79 18 82 27 23 59 66 46 21 48 95
96 83 46 49 34 88 23 42 17 27 15 54
11 88 34 92 23 62 86 56 32 32 91 54
>> reshape(permute(reshape(a,size(a,1),4,[]),[1,3,2]),[],4)
ans =
20 79 18 82
96 83 46 49
11 88 34 92
27 23 59 66
34 88 23 42
23 62 86 56
46 21 48 95
17 27 15 54
32 32 91 54
More info on the intuition behind such a General idea for nd
to nd
transformation, which even though originally was meant for NumPy/Python, extends to any programming paradigm in general.
Shrink data.frame from 8x8 to 4x4 by taking 2x2 spatial averages
From linked post, using @flodel answer, replacing sum
with mean
:
a <- as.matrix(data)
#convert matrix from char to num, ignore warnings, they are due to NAs
class(a) <- "numeric"
#adapted from @flodel https://stackoverflow.com/a/16884987/680068
res <- tapply(a, list((row(a) + 1L) %/% 2L, (col(a) + 1L) %/% 2L), mean, na.rm = TRUE)
# remove NANs
res[ is.nan(res) ] <- NA
res
# 1 2 3 4
# 1 2 3.00 2.0 1.5
# 2 4 4.00 4.0 3.5
# 3 6 5.75 6.5 6.0
# 4 8 8.50 8.5 NA
Related Topics
How to Fix Degree Symbol Not Showing Correctly in R on Linux/Fedora 31
Use Different Font Sizes for Different Portions of Text in Ggplot2 Title
Group Data Frame by Pattern in R
Passing a List of Arguments to a Function with Quasiquotation
Run R Interactively from Rscript
Pipe in Magrittr Package Is Not Working for Function Load()
Is Ifelse Ever Appropriate in a Non-Vectorized Situation and Vice-Versa
How to Calculate Euclidean Distance Between Two Matrices in R
Can't Install Any R Packages on Linux Server
How to Find Changing Points in a Dataset
An Error in R: When I Try to Apply Outer Function:
How to Create a Continuous Legend (Color Bar Style) for Scale_Alpha
Shiny Sliderinput from Max to Min
Convert Utf8 Code Point Strings Like <U+0161> to Utf8