If I have a matrix say:
> mat1=matrix(1:12, ncol=3)
> mat1
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
What do I do to replicate each column and put it next to the original so it looks like this:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 5 5 9 9
[2,] 2 2 6 6 10 10
[3,] 3 3 7 7 11 11
[4,] 4 4 8 8 12 12
I'm sure this is really simple but can't see it! Many thanks.
Try this:
mat1=matrix(1:12, ncol=3)
mat1[,rep(1:ncol(mat1),each=2)]
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 1 5 5 9 9
## [2,] 2 2 6 6 10 10
## [3,] 3 3 7 7 11 11
## [4,] 4 4 8 8 12 12
Probably easiest to re-order a simple cbind:
cbind(mat, mat)[,order(rep(1:ncol(mat), times=2))]
or
mat[,rep(1:ncol(mat), each=2)]
Related
This question already has answers here:
Change row order in a matrix/dataframe
(7 answers)
How to reverse a matrix in R? [duplicate]
(3 answers)
Closed 2 years ago.
In Matlab, I know there are some functions that can flip matrix, say flip left and right (horizontal) or up and down (vertical), but I have no idea if there are similar ones in R.
For example, assuming we have a matrix m <- matrix(1:12,nrow = 3), we want
Horizontal flip to get mh
[,1] [,2] [,3] [,4]
[1,] 10 7 4 1
[2,] 11 8 5 2
[3,] 12 9 6 3
Vertical flip to get mv
[,1] [,2] [,3] [,4]
[1,] 3 6 9 12
[2,] 2 5 8 11
[3,] 1 4 7 10
I think pracma package could help you
mh <- pracma::fliplr(m)
and
mv <- pracma::flipud(m)
such that
> mh
[,1] [,2] [,3] [,4]
[1,] 10 7 4 1
[2,] 11 8 5 2
[3,] 12 9 6 3
> mv
[,1] [,2] [,3] [,4]
[1,] 3 6 9 12
[2,] 2 5 8 11
[3,] 1 4 7 10
We can do the sequence reversed as index for column, row to get the flipped datasets
m[, ncol(m):1]
# [,1] [,2] [,3] [,4]
#[1,] 10 7 4 1
#[2,] 11 8 5 2
#[3,] 12 9 6 3
m[nrow(m):1, ]
# [,1] [,2] [,3] [,4]
#[1,] 3 6 9 12
#[2,] 2 5 8 11
#[3,] 1 4 7 10
Each loop of my sapply function will out put a n*m matrix. n is fixed, m is not.
For example, if I run this in R:
sapply(1:3, function(x) {matrix(1:9, 3)})
and it will output:
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 2 2 2
[3,] 3 3 3
[4,] 4 4 4
[5,] 5 5 5
[6,] 6 6 6
[7,] 7 7 7
[8,] 8 8 8
[9,] 9 9 9
However, what I want is something like this:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 1 4 7 1 4 7 1 4 7
[2,] 2 5 8 2 5 8 2 5 8
[3,] 3 6 9 3 6 9 3 6 9
Any idea for this? Thanks
One solution is:
do.call(cbind, lapply(1:3, function(x) {matrix(1:9, 3)}))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 1 4 7 1 4 7 1 4 7
[2,] 2 5 8 2 5 8 2 5 8
[3,] 3 6 9 3 6 9 3 6 9
We can use replicate
`dim<-`(replicate(3, matrix(1:9, 3)), c(3, 3*3))
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
#[1,] 1 4 7 1 4 7 1 4 7
#[2,] 2 5 8 2 5 8 2 5 8
#[3,] 3 6 9 3 6 9 3 6 9
Let's say I have a simple vector
v <- 1:5
I can add the vector to each element within the vector with the following code to generate the resulting matrix.
matrix(rep(v, 5), nrow=5, byrow=T) + matrix(rep(v, 5), nrow=5)
[,1] [,2] [,3] [,4] [,5]
[1,] 2 3 4 5 6
[2,] 3 4 5 6 7
[3,] 4 5 6 7 8
[4,] 5 6 7 8 9
[5,] 6 7 8 9 10
But this seems verbose and inefficient. Is there a more concise way to accomplish this? Perhaps some linear algebra concept that is evading me?
outer should do what you want
outer(v, v, `+`)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 2 3 4 5 6
# [2,] 3 4 5 6 7
# [3,] 4 5 6 7 8
# [4,] 5 6 7 8 9
# [5,] 6 7 8 9 10
Posting this answer not for up votes but to highlight Franks comment. You can use
sapply(v,"+",v)
For, example I if a had matrix like this:
realmatrix=matrix(1:16,ncol=4,nrow=4)
Which would give this:
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
And I would like to make a function that would replace the two columns with a certain value ( for example 1:4) if it has a even number of colums, then the result should be something like this:
[,1] [,2] [,3] [,4]
[1,] 1 1 1 13
[2,] 2 2 2 14
[3,] 3 3 3 15
[4,] 4 4 4 16
And if the matrix has odd numbers of colums, the function should replace only the odd column, that is to say the central one:
This is the matrix with odd numbers of columns:
realmatrix2=matrix(1:12,ncol=3,nrow=4)
The final result:
[,1] [,2] [,3]
[1,] 1 1 9
[2,] 2 2 10
[3,] 3 3 11
[4,] 4 4 12
Thanks a lot!
Try:
fun2 <- function(mat, val){
stopifnot(length(val)==nrow(mat))
n <- ncol(mat)
if( (n/2) %%2 ==0){
mat[, c(n/2, n/2+1)] <- val
}
else {
mat[, ceiling(n/2)] <- val
}
mat
}
fun2(realmatrix, 1:4)
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 13
#[2,] 2 2 2 14
#[3,] 3 3 3 15
#[4,] 4 4 4 16
fun2(realmatrix2,1:4)
# [,1] [,2] [,3]
#[1,] 1 1 9
#[2,] 2 2 10
#[3,] 3 3 11
#[4,] 4 4 12
realmatrix5=matrix(1:32, ncol=8,nrow=4)
fun2(realmatrix5, 1:4)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#[1,] 1 5 9 1 1 21 25 29
#[2,] 2 6 10 2 2 22 26 30
#[3,] 3 7 11 3 3 23 27 31
#[4,] 4 8 12 4 4 24 28 32
Update
If you want to change the rows:
funR <- function(mat, val){
stopifnot(length(val)==ncol(mat))
n <- nrow(mat)
if((n/2) %%2==0){
mat[c(n/2, n/2+1),] <- rep(val, each=2)
}
else {
mat[ceiling(n/2),] <- val
}
mat
}
funR(realmatrix, 1:4)
# [,1] [,2] [,3] [,4]
#[1,] 1 5 9 13
#[2,] 1 2 3 4
#[3,] 1 2 3 4
#[4,] 4 8 12 16
realmatrix3 <- matrix(1:15, ncol=5)
funR(realmatrix3, 1:5)
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 4 7 10 13
#[2,] 1 2 3 4 5
#[3,] 3 6 9 12 15
Hi everyone who loves while hates R:
Let's say you want to turn matrix M
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[3,] 7 8 9
to N
[,1] [,2] [,3]
[1,] 3 2 1
[2,] 6 5 4
[3,] 9 8 7
All you need to do is
N<-M[,c(3:1)]
And N's structure is still a matrix
However, when you want to turn matrix M
[,1] [,2] [,3]
[1,] 1 2 3
to N
[,1] [,2] [,3]
[1,] 3 2 1
if you do
N<-M[,c(3:1)]
R will give you
N
[1] 3 2 1
N now is a vector! Not a matrix!
My solution is
N<-M%*%diag(3)[,c(3:1)]
which needs big space to store the identity matrix however.
Any better idea?
You're looking for this:
N<-M[,c(3:1),drop = FALSE]
Read ?Extract for more information. This is also a FAQ. This behavior is one of the most common debates folks have about the way things "should" be in R. My general impression is that many people agree that drop = FALSE might be a more sensible default, but that behavior is so old that changing it would be enormously disruptive to vast swaths of existing code.
A=t(matrix(1:25,5,5))
B=matrix(0,5,5)
for(i in 1:5){
B[i,(nrow(A)+1-i)]=1
}
A
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 2 3 4 5
# [2,] 6 7 8 9 10
# [3,] 11 12 13 14 15
# [4,] 16 17 18 19 20
# [5,] 21 22 23 24 25
A%*%B
# [,1] [,2] [,3] [,4] [,5]
# [1,] 5 4 3 2 1
# [2,] 10 9 8 7 6
# [3,] 15 14 13 12 11
# [4,] 20 19 18 17 16
# [5,] 25 24 23 22 21