knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) library(cuadramelo) set.seed(2) example_matrix <- rnorm(3*5) |> matrix(3,5) |> round(3) col_totals <- c( 0.870, -1.070, 3.450, 0.260, 1.350) row_totals <- c(-1.851, 0.243, 6.468)
This section is concerned with the problem of slightly adjusting a matrix so that its row and column totals add up to given vector using balance_matrix()
.
Remark: In order for the adjustment to be possible, the sum of those two vectors must be the same. This only makes sense, because both must equal the sum of the whole resulting matrix.
Consider the example matrix
example_matrix
and the desired row totals
row_totals
and column totals,
col_totals
which are mildly different from those of the matrix.
colSums(example_matrix) - col_totals rowSums(example_matrix) - row_totals
Let's use our function to solve this problem.
tallied_matrix <- balance_matrix(example_matrix, col_totals, row_totals) tallied_matrix - example_matrix (rowSums(tallied_matrix) - row_totals) |> round(7) (colSums(tallied_matrix) - col_totals) |> round(7)
We don't need to provide both the row and column totals. If only the column totals (or rows) are provided, the tallying is done to match only those.
tallied_matrix <- balance_matrix(example_matrix, col_totals) tallied_matrix - example_matrix (rowSums(tallied_matrix) - row_totals) |> round(7) (colSums(tallied_matrix) - col_totals) |> round(7)
Sometimes one may need to balance a matrix that is made up of blocks. For example, suppose that the following $16\times4$ matrix is composed of 4 vertical $4\times 2$ blocks.
set.seed(10) block_matrix <- (rnorm(32)*10) |> matrix(ncol = 2) |> round(3) block_col_totals <- aggregate(block_matrix, by = list(rep(1:4, times = rep(4,4))), FUN = sum)[, -1] |> round() |> unname() |> as.matrix()
block_matrix
And we have the following matrix whose rows are the desired column totals for each of the blocks.
block_col_totals
The balance_by_blocks()
function applies balance_matrix()
to each block using the totals given by the argument col_totals
. When the blocks are distributed vertically (layout = 2
), this argument must be a matrix as wide as the matrix to be balanced (Y
), and with a row for each block. We have to indicate also that the bloks are 4 rows long (L = 4
). Blocks are assumed to be as wide as the matrix (or as tall as the matrix if distributed horizontally).
X <- balance_by_blocks(block_matrix, col_totals = block_col_totals, layout = 2, L = 4) X[9:12,] - balance_matrix(block_matrix[9:12,], block_col_totals[3,])
Just as with balance_matrix()
, both col_totals
and row_totals
can be provided. In the case of vertically distributed blocks, row_totals
is a vector with an entry for each row of the Y
matrix. The function solves the problem independently for each block.
The blocks can be distributed horizontally and analogous considerations apply.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.