Related
I am trying to add two matrices with different dimension in R. Ideally, the system should equate two matrices adding missing rows/columns, filled with zeros. For instance, if we have one matrix with 1:4 rows and another with 1:5 rows and their number of columns is identical. So to add the two matrices we need to add to the first matrix the fifth row full of zeros.
Could you please help.
#Matrix1
a11<-matrix(c(419371623, 10990236, 29346292, 0, 0, 39386246.52, 0, 0,0 ,0,0, 0, 0, 0, 30174248.77,0, 27839925.91, 0 ,0 ,112921829.5),4,5,dimnames = list(c(1,2,3,5),c(1,2,3,4,5)),byrow=TRUE)
#Matrix 2
a22<-matrix(c(853624485, 0, 766111,0, 0, 20240075.89 ,0, 4839059.2,0, 2062687.122 ,0, 0,0 ,0 ,0 ,7282484.458,0, 18738621.67 ,0 ,0),5,4,byrow=TRUE, list(c(1:5),c(1:4)))
#Expected Result:
res<- matrix(c(1272996108, 10990236, 30112402.72, 0, 0,
39386247, 20240075.89, 0, 48390599.21, 0,
0, 2062687.122 ,0, 0, 30174249,
0, 27839926, 0, 7282484.458, 112921830,
0, 18738622, 0, 0, 0), 5, 5, byrow=TRUE, dimnames = list(1:5,1:5)
You could write your own function to perform this:
`%+%` <- function(a, b){
i <- dim(a)
j <- dim(b)
out <- pmax(i,j)
valid <- pmin(i,j)
result <- matrix(0, out[1], out[2])
v_row <- seq(valid[1])
v_col <- seq(valid[2])
result[v_row, v_col] <- a[v_row, v_col] + b[v_row, v_col]
ind1 <- which(result[seq(i[1]), seq(i[2])] == 0 & a!=0, TRUE)
result[ind1] <- a[ind1]
ind2 <- which(result[seq(j[1]), seq(j[2])] == 0 & b!=0, TRUE)
result[ind2] <- b[ind2]
result
}
a11%+%a22
[,1] [,2] [,3] [,4] [,5]
[1,] 1272996108 10990236 30112403 0 0
[2,] 39386247 20240076 0 4839059 0
[3,] 0 2062687 0 0 30174249
[4,] 0 27839926 0 7282484 112921830
[5,] 0 18738622 0 0 0
s1 <- matrix(1,3,5)
s2 <- matrix(2, 5,2)
s1
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 1 1
[2,] 1 1 1 1 1
[3,] 1 1 1 1 1
s2
[,1] [,2]
[1,] 2 2
[2,] 2 2
[3,] 2 2
[4,] 2 2
[5,] 2 2
s1 %+% s2
[,1] [,2] [,3] [,4] [,5]
[1,] 3 3 1 1 1
[2,] 3 3 1 1 1
[3,] 3 3 1 1 1
[4,] 2 2 0 0 0
[5,] 2 2 0 0 0
Maybe there is a shorter/better way to make the dimension of both the matrix equal but here is one way.
n <- max(ncol(a11), ncol(a22))
m <- max(nrow(a11), nrow(a22))
if(m > ncol(a11)) a11 <- cbind(a11, matrix(0, ncol = m - ncol(a11), nrow = nrow(a11)))
if(m > ncol(a22)) a22 <- cbind(a22, matrix(0, ncol = m - ncol(a22), nrow = nrow(a22)))
if(n > nrow(a11)) a11 <- rbind(a11, matrix(0, ncol = ncol(a11), nrow = n - nrow(a11)))
if(n > nrow(a22)) a11 <- rbind(a11, matrix(0, ncol = ncol(a12), nrow = n - nrow(a22)))
Now a11 and a22 are of same dimension so you can add them :
a11 + a22
# 1 2 3 4 5
#1 1272996108 10990236 30112403 0 0
#2 39386247 20240076 0 4839059 0
#3 0 2062687 0 0 30174249
#5 0 27839926 0 7282484 112921830
# 0 18738622 0 0 0
After initializing res to zero, I am adding the matrices by indices.
Easily extendable to add more matrices.
# initilize res
res <- matrix(0, nrow = max(nrow(a11), nrow(a22)),
ncol = max(ncol(a11), ncol(a22)))
# index of a11
inds <- which(!is.na(a11), arr.ind = T)
res[inds] <- res[inds] + a11[inds]
# index of a22
inds <- which(!is.na(a22), arr.ind = T)
res[inds] <- res[inds] + a22[inds]
# repeat for a33 etc if there's more.
Results with a11 and a22
> res
[,1] [,2] [,3] [,4] [,5]
[1,] 1272996108 10990236 30112403 0 0
[2,] 39386247 20240076 0 4839059 0
[3,] 0 2062687 0 0 30174249
[4,] 0 27839926 0 7282484 112921830
[5,] 0 18738622 0 0 0
How can I create all binary combinations of matrices with the condition that there can only be a single 1 per column and row. The example will clarify. This particular example must have 6 matrices of combinations, I am showing only the first 2.
c1 <- matrix(c(1, 0, 0, 0, 1, 0, 0, 0, 1), nrow = 3) #First combination
c2 <- matrix(c(0, 1, 0, 1, 0, 0, 0, 0, 1), nrow = 3) #Second combination
What you are asking for is equivalent to finding all permutations of length = n where n = nrow(c1) (or c2 above). Using the FUN argument of permuteGeneral from RcppAlgos (I am the author), we can easily generate the desired outcome:
n <- 3L
myIdentity <- diag(nrow = n)
library(RcppAlgos)
permuteGeneral(n, n, FUN = function(x) myIdentity[x, ])
[[1]]
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
[[2]]
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 0 1
[3,] 0 1 0
[[3]]
[,1] [,2] [,3]
[1,] 0 1 0
[2,] 1 0 0
[3,] 0 0 1
[[4]]
[,1] [,2] [,3]
[1,] 0 1 0
[2,] 0 0 1
[3,] 1 0 0
[[5]]
[,1] [,2] [,3]
[1,] 0 0 1
[2,] 1 0 0
[3,] 0 1 0
[[6]]
[,1] [,2] [,3]
[1,] 0 0 1
[2,] 0 1 0
[3,] 1 0 0
There are many other ways of generating the requested output. Most notably, utilizing the tried and true combinat package, we can get a similar result (the output will be in a different order):
combinat::permn(3, fun = function(x) myIdentity[x, ])
Now that we have reduced the problem to simply generating permutations, we can use any of the great packages (arrangements, gtools, multicool, partitions, etc.) for generating permutations to obtain our desired result with the help of lapply:
library(arrangements)
myPerms <- permutations(n)
lapply(1:nrow(myPerms), function(x) myIdentity[myPerms[x,], ])
I have solution matrix(say A) to the indefinite equation x1+x2+x3+x4 = 6. Also, I have another matrix(say B) with columns are
0 1 0 1
0 0 1 1
I want to generate matrices using rows of A and the columns of B.
For an example, let (2,0,1,3) is the one solution(one row) of the matrix A. Then, the columns of my new matrix are
0 0 0 1 1 1
0 0 1 1 1 1
Columns of this new matrix are the multiples of columns of B. i.e., first column 2-times, third column 1-time and fourth column 3-times. I want to use this procedure all the rows of matrix A.
use rep:
b <- matrix(c(0, 0, 1, 0, 0, 1, 1, 1), nrow = 2)
a <- c(2, 0, 1, 3)
b[, rep(1:ncol(b), a)]
if a has many rows:
lapply(1:nrow(a), function(i) b[, rep(1:ncol(b), a[i, ])])
> B <- rbind(c(0, 1, 0, 1), c( 0, 0, 1, 1))
> A <- rbind(c(2,0,1,3), c(2,0,1,3))
> do.call(rbind, lapply(1:nrow(A), function(jj) t(sapply(1:nrow(B), function(j) do.call(c, lapply(1:4, function(i) rep(B[j,i], A[jj,i]))) ))))
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 0 0 0 1 1 1
[2,] 0 0 1 1 1 1
[3,] 0 0 0 1 1 1
[4,] 0 0 1 1 1 1
I'm doing some kind of optical character recognition and face the following issue. I store the glyphs in a list of binary matrices and they can be of different size, but their maximum possible width is wid = 3 columns (may be any defined constant, not just 3). In some cases after the first stage of processing I get data which look like this:
myll <- list(matrix(c(0, 0, 0, 1, 1, 0), ncol = 2),
matrix(c(0), ncol = 1),
matrix(c(1, 1, 0), ncol = 3),
matrix(c(1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1), ncol = 7),
matrix(c(1, 1, 1, 1), ncol = 2))
# [[1]]
# [,1] [,2]
# [1,] 0 1
# [2,] 0 1
# [3,] 0 0
#
# [[2]]
# [,1]
# [1,] 0
#
# [[3]]
# [,1] [,2] [,3]
# [1,] 1 1 0
#
# [[4]]
# [,1] [,2] [,3] [,4] [,5] [,6] [,7]
# [1,] 1 1 1 0 0 0 1
# [2,] 0 1 0 1 0 0 1
# [3,] 1 1 1 1 0 0 1
#
# [[5]]
# [,1] [,2]
# [1,] 1 1
# [2,] 1 1
So, some glyphs may be not separated for some reasons. This happens only with glyphs of maximum possible width. Moreover, there may be some junk at the end of the matrix. I have to split them into matrices of width ncol = wid leaving the last piece (junk) as is. Then I store this matrices in separate elements of list to get the following output:
# [[1]]
# [,1] [,2]
# [1,] 0 1
# [2,] 0 1
# [3,] 0 0
#
# [[2]]
# [,1]
# [1,] 0
#
# [[3]]
# [,1] [,2] [,3]
# [1,] 1 1 0
#
# [[4]]
# [,1] [,2] [,3]
# [1,] 1 1 1
# [2,] 0 1 0
# [3,] 1 1 1
#
# [[5]]
# [,1] [,2] [,3]
# [1,] 0 0 0
# [2,] 1 0 0
# [3,] 1 0 0
#
# [[6]]
# [,1]
# [1,] 1
# [2,] 1
# [3,] 1
#
# [[7]]
# [,1] [,2]
# [1,] 1 1
# [2,] 1 1
At the moment I can make it with the help of this functions
checkGlyphs <- function(gl_m, wid = 3) {
if (ncol(gl_m) > wid)
return(list(gl_m[,1:wid], matrix(gl_m[,-(1:wid)], nrow = nrow(gl_m)))) else
return(gl_m)
}
separateGlyphs <- function(myll, wid = 3) {
require("magrittr")
presplit <- lapply(myll, checkGlyphs, wid)
total_new_length <-
presplit[unlist(lapply(presplit, is.list))] %>% lapply(length) %>% unlist() %>% sum() +
as.integer(!unlist(lapply(presplit, is.list))) %>% sum()
splitted <- vector("list", length = total_new_length)
spl_index <- 1
for (i in 1:length(presplit))
{
if (!is.list(presplit[[i]]))
{
splitted[[spl_index]] <- presplit[[i]]
spl_index <- spl_index + 1
} else
{
for (j in 1:length(presplit[[i]]))
{
splitted[[spl_index]] <- presplit[[i]][[j]]
spl_index <- spl_index + 1
}
}
}
if (any(lapply(splitted, ncol) > wid)) return(separateGlyphs(splitted, wid)) else
return(splitted)
}
But I believe there is more fast and convenient way to achieve the same result (without using for loops and this enlooped reassignment of elements and then recursion if needed O_o).
I will be thankful for any suggestions on the point or, alternatively, for recommending some OCR-packages for R.
This should do the trick, with the values in final being what you're after.
combined <- do.call(cbind, lapply(myll, unlist))
idx <- seq(1, ncol(combined), 2)
final <- do.call(list, lapply(idx, function(x) combined[, x:(x+1)]))
I use a r-matrix (for example [[0,0,0,1],[0,1,0,1],[1,0,0,0],[0,0,1,1]]) representing
a raster. I'd like to replace every value except 0 with its row index value. Is there something like
matrix[matrix==1] <- row_index
so that my result would look like [[0,0,0,1],[0,2,0,2],[3,0,0,0],[0,0,4,4]]?
I am using R 2.15.1 on a Mac (10.7.5) and RPY2 2.2.6 to start the R-Methods.
Or is there any other way to get reasonable results for statistical functions like histogram, chi_square etc.?
For a succinct, expressive solution, I'd be likely to use this:
m <- matrix(c(0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1),
nrow = 4, byrow = TRUE)
m[m!=0] <- row(m)[m!=0]
m
# [,1] [,2] [,3] [,4]
# [1,] 0 0 0 1
# [2,] 0 2 0 2
# [3,] 3 0 0 0
# [4,] 0 0 4 4
Hopefully all hell won't break loose for suggesting a for loop, but we'll see:
Here's your matrix
mymat <- matrix(c(0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1),
nrow = 4, byrow = TRUE)
mymat
# [,1] [,2] [,3] [,4]
# [1,] 0 0 0 1
# [2,] 0 1 0 1
# [3,] 1 0 0 0
# [4,] 0 0 1 1
Here's a for loop that uses basic subsetting to identify the cases you want to replace.
for (i in 1:nrow(mymat)) {
mymat[i, ][mymat[i, ] != 0] <- i
}
Here's the result.
mymat
# [,1] [,2] [,3] [,4]
# [1,] 0 0 0 1
# [2,] 0 2 0 2
# [3,] 3 0 0 0
# [4,] 0 0 4 4
Maybe I'm missing the point of your question, but how about
> m <- matrix(c(0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1),
+ nrow = 4, byrow = TRUE)
> m * 1:nrow(m)
[,1] [,2] [,3] [,4]
[1,] 0 0 0 1
[2,] 0 2 0 2
[3,] 3 0 0 0
[4,] 0 0 4 4
>
(ETA: R fills in matrices by column, and the itemwise product operator makes the two matrices involved conformant by replicating them column by column until they fit. The * operator here winds up multiplying each item by the row to which it belongs.)