Combining matrices by alternating columns - r

I'm looking for a general approach to combine two matrices so that the columns from the two initial matrices alternate in the new matrix
col1m1...col1m2...col2m1...col2m2...col3m1...col3m2......
for example:
matrix.odd <- matrix(c(rep(1,3),rep(3,3),rep(5,3)),nrow=3,ncol=3)
matrix.even <- matrix(c(rep(2,3),rep(4,3),rep(6,3)),nrow=3,ncol=3)
# would look like
matrix.combined <- matrix(c(rep(1,3),rep(2,3),rep(3,3),rep(4,3),rep(5,3),rep(6,3)),
nrow=3,ncol=6)
I'm looking for a general approach because I will have matrix combinations with more than just 3 columns. I've tried some for loops and some if statements but it isn't really coming together for me. Searches on combining matrices with shuffle and with alternation have not proven fruitful either. Any thoughts?

Smth like this should do:
m <- cbind(matrix.odd, matrix.even) # combine
m <- m[, c(matrix(1:ncol(m), nrow = 2, byrow = T))] # then reorder
Another option for fun:
matrix(rbind(matrix.odd, matrix.even), nrow = nrow(matrix.odd))
And to play the many matrices game:
weave = function(...) {
l = list(...)
matrix(do.call(rbind, l), nrow = nrow(l[[1]]))
}

rows.combined <- nrow(matrix.odd)
cols.combined <- ncol(matrix.odd) + ncol(matrix.even)
matrix.combined <- matrix(NA, nrow=rows.combined, ncol=cols.combined)
matrix.combined[, seq(1, cols.combined, 2)] <- matrix.odd
matrix.combined[, seq(2, cols.combined, 2)] <- matrix.even

alternate.cols <- function(m1, m2) {
cbind(m1, m2)[, order(c(seq(ncol(m1)), seq(ncol(m2))))]
}
identical(matrix.combined, alternate.cols(matrix.odd, matrix.even))
# [1] TRUE
which also does the right thing (subjective) if m1 and m2 have a different number of columns:
alternate.cols(matrix.odd, matrix.even[, -3])
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 2 3 4 5
# [2,] 1 2 3 4 5
# [3,] 1 2 3 4 5
It is easy to generalize to any number of matrices:
alternate.cols <- function(...) {
l <- list(...)
m <- do.call(cbind, l)
i <- order(sequence(sapply(l, ncol)))
m[, i]
}

You could turn into a 3D array and then transpose...
arr <- array( c(m1,m2) , dim = c(dim(m1),2) )
matrix( aperm( arr , c(1,3,2) ) , nrow(m1) )
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 4 5 6
[2,] 1 2 3 4 5 6
[3,] 1 2 3 4 5 6
And as a function, generalisable to many matrices...
bindR <- function(...){
args <- list(...)
dims <- c( dim(args[[1]]) , length(args) )
arr <- array( unlist( args ) , dim = dims )
matrix( aperm( arr , c(1,3,2) ) , dims[1] )
}
bindR(m1,m2,m1,m2)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
#[1,] 1 2 1 2 3 4 3 4 5 6 5 6
#[2,] 1 2 1 2 3 4 3 4 5 6 5 6
#[3,] 1 2 1 2 3 4 3 4 5 6 5 6

There is likely a more succinct way to do this. If the matrices are large, you will likely need to look for a more efficient method.
# Test data
(X <- matrix(1:16, nrow=4, ncol=4))
(Y <- matrix(-16:-1, nrow=4, ncol=4))
# Set indices for the new matrix
X.idx <- seq(1, ncol(X)*2, by=2)
Y.idx <- seq(2, ncol(Y)*2+1, by=2)
# Column bind the matrices and name columns according to the indices
XY <- cbind(X, Y)
colnames(XY) <- c(X.idx, Y.idx)
# Now order the columns
XY[, order(as.numeric(colnames(XY)))]

Related

I have a table consists of many samples across many columns, how to substract the value of each sample in each column to the mean of their column? [duplicate]

I have a matrix with 5 columns and 4 rows. I also have a vector with 3 columns. I want to subtract the values in the vector from columns 3,4 and 5 respectively at each row of the matrix.
b <- matrix(rep(1:20), nrow=4, ncol=5)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 9 13 17
[2,] 2 6 10 14 18
[3,] 3 7 11 15 19
[4,] 4 8 12 16 20
c <- c(5,6,7)
to get
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 4 7 10
[2,] 2 6 5 8 11
[3,] 3 7 6 9 12
[4,] 4 8 7 10 13
This is exactly what sweep was made for:
b <- matrix(rep(1:20), nrow=4, ncol=5)
x <- c(5,6,7)
b[,3:5] <- sweep(b[,3:5], 2, x)
b
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 5 4 7 10
#[2,] 2 6 5 8 11
#[3,] 3 7 6 9 12
#[4,] 4 8 7 10 13
..or even without subsetting or reassignment:
sweep(b, 2, c(0,0,x))
Perhaps not that elegant, but
b <- matrix(rep(1:20), nrow=4, ncol=5)
x <- c(5,6,7)
b[,3:5] <- t(t(b[,3:5])-x)
should do the trick. We subset the matrix to change only the part we need, and we use t() (transpose) to flip the matrix so simple vector recycling will take care of subtracting from the correct row.
If you want to avoid the transposed, you could do something like
b[,3:5] <- b[,3:5]-x[col(b[,3:5])]
as well. Here we subset twice, and we use the second to get the correct column for each value in x because both those matrices will index in the same order.
I think my favorite from the question that #thelatemail linked was
b[,3:5] <- sweep(b[,3:5], 2, x, `-`)
Another way, with apply:
b[,3:5] <- t(apply(b[,3:5], 1, function(x) x-c))
A simple solution:
b <- matrix(rep(1:20), nrow=4, ncol=5)
c <- c(5,6,7)
for(i in 1:nrow(b)) {
b[i,3:5] <- b[i,3:5] - c
}
This can be done with the rray package in a very satisfying way (using its (numpy-like) broadcasting - operator %b-%):
#install.packages("rray")
library(rray)
b <- matrix(rep(1:20), nrow=4, ncol=5)
x <- c(5, 6, 7)
b[, 3:5] <- b[, 3:5] %b-% matrix(x, 1)
b
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 1 5 4 7 10
#> [2,] 2 6 5 8 11
#> [3,] 3 7 6 9 12
#> [4,] 4 8 7 10 13
For large matrices this is even faster than sweep:
#install.packages("bench")
res <- bench::press(
size = c(10, 1000, 10000),
frac_selected = c(0.1, 0.5, 1),
{
B <- matrix(sample(size*size), nrow=size, ncol=size)
B2 <- B
x <- sample(size, size=ceiling(size*frac_selected))
idx <- sample(size, size=ceiling(size*frac_selected))
bench::mark(rray = {B2[, idx] <- B[, idx, drop = FALSE] %b-% matrix(x, nrow = 1); B2},
sweep = {B2[, idx] <- sweep(B[, idx, drop = FALSE], MARGIN = 2, x); B2}
)
}
)
plot(res)

'No such index at level 1' error on for loop to add columns

I have a list of matrices. Each matrix has either 11 or 12 columns, so I'm trying to standardize all of the matrices to have 12 columns.
# Normalize all pages to have 12 columns; some currently have 11 others 12
# 'out' is a list with each element being a matrix
for (i in out) {
# check if each matrix has less than 12 columns
if(ncol(out[[i]])<12) {
# if it does, then insert a column of blanks between columns 1 and 2
out1 = out[[i]]
out2 <- cbind(out1[,1],"",out1[,2:11])
out[[i]] <- out2
}
}
When I run the code, I get the following message:
Error in out[[i]] : no such index at level 1
Any ideas?
Here's a generalized way to do this using lapply -
# first a reproducible example
matlist <- list(
a = matrix(1:6, ncol = 3),
b = matrix(1:4, ncol = 2)
)
matlist
$a
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
$b
[,1] [,2]
[1,] 1 3
[2,] 2 4
Now, similar to the problem, all matrices should have 3 columns where missing column(s) are inserted between column 1 and 2 -
# get max column number from list
maxcol <- max(sapply(matlist, ncol)) # directly use 12 here if preferred
# update original list
matlist[] <- lapply(matlist, function(x) {
coldiff <- maxcol - ncol(x)
if(coldiff > 0) {
cbind(x[, 1], matrix(NA, nrow(x), coldiff), x[, 2:ncol(x)])
} else {
x
}
})
matlist
$a
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
$b
[,1] [,2] [,3]
[1,] 1 NA 3
[2,] 2 NA 4

Simplest way to repeat matrix along 3rd dimension

How to repeat a matrix A along 3rd dimension n times? array(rep(A,n),c(dim(A),n)) should work but is there a simpler way? I was hoping A[,,rep(1,n)] would do the trick but apparently not.
You forgot to change the dimensions first:
A = matrix(1:4, nrow = 2)
dim(A) = c(dim(A), 1)
A[, , rep(1, 3)]
#, , 1
#
# [,1] [,2]
#[1,] 1 3
#[2,] 2 4
#
#, , 2
#
# [,1] [,2]
#[1,] 1 3
#[2,] 2 4
#
#, , 3
#
# [,1] [,2]
#[1,] 1 3
#[2,] 2 4
I guess the following is a little shorter:
myArray <- replicate(n, A)
Here is an example:
temp <- matrix(1:10, 5)
replicate(3, temp)

Matrix without the matrix function

I m trying to create a matrix in R without using matrix function I tried
this but it works just for 2 rows how do I specify nrows I have no idea
matrix2<-function(n)
{
d<-n/2
v1<-c(1:d)
v2<-c(d +1:n)
x<- rbind(v1,v2)
return(x)
}
I want to create a matrix without using the matrix function and byrow not bycolmun
exemple
a function I enter number of columns and the dimension N in my exemple and in return it creates a matrix
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
[4,] 7 8
for exepmle
This will give you a matrix for a specified number of columns. I wasn't sure what you meant with dimension N.
matrix2 <- function(N, columns){
d<-ceiling(N/columns) # rounds up to first integer
x <- c()
i <- 1
for(row in 1:d){
x <- rbind(x, c(i:(i+columns-1)))
i <- i+columns
}
return(x)
}
> matrix2(8,2)
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
[4,] 7 8
You can also use an indirection via a list. Then you can also set both, the column and the row number. And how the matrix is filled, row wise or column wise.
matrix2<-function(n,m,V,byRow=T){
if(length(V) != n*m ) warning("length of the vector and rows*columns differs" )
# split the vector
if(byRow) r <- n
if(!byRow) r <- m
fl <- 1:r # how often you have to split
fg <- sort(rep_len(fl,length(V))) # create a "splitting-vector"
L <- split(V,fg)
# convert the list to a matrix
if(byRow) res <- do.call(rbind,L)
if(!byRow) res <- do.call(cbind,L)
rownames(res) <- colnames(res) <- NULL
res #output
}
matrix2(2,4,1:8,F)
[,1] [,2] [,3] [,4]
[1,] 1 3 5 7
[2,] 2 4 6 8
matrix2(2,4,1:8,T)
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8

subtract a constant vector from each row in a matrix in r

I have a matrix with 5 columns and 4 rows. I also have a vector with 3 columns. I want to subtract the values in the vector from columns 3,4 and 5 respectively at each row of the matrix.
b <- matrix(rep(1:20), nrow=4, ncol=5)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 9 13 17
[2,] 2 6 10 14 18
[3,] 3 7 11 15 19
[4,] 4 8 12 16 20
c <- c(5,6,7)
to get
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 4 7 10
[2,] 2 6 5 8 11
[3,] 3 7 6 9 12
[4,] 4 8 7 10 13
This is exactly what sweep was made for:
b <- matrix(rep(1:20), nrow=4, ncol=5)
x <- c(5,6,7)
b[,3:5] <- sweep(b[,3:5], 2, x)
b
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 5 4 7 10
#[2,] 2 6 5 8 11
#[3,] 3 7 6 9 12
#[4,] 4 8 7 10 13
..or even without subsetting or reassignment:
sweep(b, 2, c(0,0,x))
Perhaps not that elegant, but
b <- matrix(rep(1:20), nrow=4, ncol=5)
x <- c(5,6,7)
b[,3:5] <- t(t(b[,3:5])-x)
should do the trick. We subset the matrix to change only the part we need, and we use t() (transpose) to flip the matrix so simple vector recycling will take care of subtracting from the correct row.
If you want to avoid the transposed, you could do something like
b[,3:5] <- b[,3:5]-x[col(b[,3:5])]
as well. Here we subset twice, and we use the second to get the correct column for each value in x because both those matrices will index in the same order.
I think my favorite from the question that #thelatemail linked was
b[,3:5] <- sweep(b[,3:5], 2, x, `-`)
Another way, with apply:
b[,3:5] <- t(apply(b[,3:5], 1, function(x) x-c))
A simple solution:
b <- matrix(rep(1:20), nrow=4, ncol=5)
c <- c(5,6,7)
for(i in 1:nrow(b)) {
b[i,3:5] <- b[i,3:5] - c
}
This can be done with the rray package in a very satisfying way (using its (numpy-like) broadcasting - operator %b-%):
#install.packages("rray")
library(rray)
b <- matrix(rep(1:20), nrow=4, ncol=5)
x <- c(5, 6, 7)
b[, 3:5] <- b[, 3:5] %b-% matrix(x, 1)
b
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 1 5 4 7 10
#> [2,] 2 6 5 8 11
#> [3,] 3 7 6 9 12
#> [4,] 4 8 7 10 13
For large matrices this is even faster than sweep:
#install.packages("bench")
res <- bench::press(
size = c(10, 1000, 10000),
frac_selected = c(0.1, 0.5, 1),
{
B <- matrix(sample(size*size), nrow=size, ncol=size)
B2 <- B
x <- sample(size, size=ceiling(size*frac_selected))
idx <- sample(size, size=ceiling(size*frac_selected))
bench::mark(rray = {B2[, idx] <- B[, idx, drop = FALSE] %b-% matrix(x, nrow = 1); B2},
sweep = {B2[, idx] <- sweep(B[, idx, drop = FALSE], MARGIN = 2, x); B2}
)
}
)
plot(res)

Resources