I have a matrix in R like this:
|1|2|3|
|1|2|3|
|1|2|3|
Is there an easy way to rotate the entire matrix by 90 degrees clockwise to get these results?
|1|1|1|
|2|2|2|
|3|3|3|
and again rotating 90 degrees:
|3|2|1|
|3|2|1|
|3|2|1|
?
t does not rotate the entries, it flips along the diagonal:
x <- matrix(1:9, 3)
x
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
t(x)
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
## [3,] 7 8 9
90 degree clockwise rotation of R matrix:
You need to also reverse the columns prior to the transpose:
rotate <- function(x) t(apply(x, 2, rev))
rotate(x)
## [,1] [,2] [,3]
## [1,] 3 2 1
## [2,] 6 5 4
## [3,] 9 8 7
rotate(rotate(x))
## [,1] [,2] [,3]
## [1,] 9 6 3
## [2,] 8 5 2
## [3,] 7 4 1
rotate(rotate(rotate(x)))
## [,1] [,2] [,3]
## [1,] 7 8 9
## [2,] 4 5 6
## [3,] 1 2 3
rotate(rotate(rotate(rotate(x))))
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
90 degree counter clockwise rotation of R matrix:
Doing the transpose prior to the reverse is the same as rotate counter clockwise:
foo = matrix(1:9, 3)
foo
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
foo <- apply(t(foo),2,rev)
foo
## [,1] [,2] [,3]
## [1,] 7 8 9
## [2,] 4 5 6
## [3,] 1 2 3
m <- matrix(rep(1:3,each=3),3)
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 1 2 3
[3,] 1 2 3
t(m[nrow(m):1,])
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 2 2 2
[3,] 3 3 3
m[nrow(m):1,ncol(m):1]
[,1] [,2] [,3]
[1,] 3 2 1
[2,] 3 2 1
[3,] 3 2 1
t(m)[ncol(m):1,]
[,1] [,2] [,3]
[1,] 3 3 3
[2,] 2 2 2
[3,] 1 1 1
An easy way to rotate a matrix by 180° is this:
m <- matrix(1:8,ncol=4)
# [,1] [,2] [,3] [,4]
# [1,] 1 3 5 7
# [2,] 2 4 6 8
rot <- function(x) "[<-"(x, , rev(x))
rot(m)
# [,1] [,2] [,3] [,4]
# [1,] 8 6 4 2
# [2,] 7 5 3 1
rot(rot(m))
# [,1] [,2] [,3] [,4]
# [1,] 1 3 5 7
# [2,] 2 4 6 8
R methods to rotate a matrix 90 degrees and -90 degrees
#first reverse, then transpose, it's the same as rotate 90 degrees
rotate_clockwise <- function(x) { t( apply(x, 2, rev))}
#first transpose, then reverse, it's the same as rotate -90 degrees:
rotate_counter_clockwise <- function(x) { apply( t(x),2, rev)}
#or if you want a library to help make things easier to read:
#install.packages("pracma")
library(pracma)
rotate_one_eighty <- function(x) { rot90(x, 2) }
rotate_two_seventy <- function(x) { rot90(x, -1) }
foo = matrix(1:9, 3)
foo
foo = rotate_clockwise(foo)
foo
foo = rotate_counter_clockwise(foo)
foo
foo = rotate_one_eighty(foo)
foo
Prints:
[,1] [,2] [,3]
[1,] 1 4 7 #original matrix
[2,] 2 5 8
[3,] 3 6 9
[,1] [,2] [,3]
[1,] 3 2 1
[2,] 6 5 4 #rotated 90 degrees
[3,] 9 8 7
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8 #rotated -90 degrees
[3,] 3 6 9
[,1] [,2] [,3]
[1,] 9 6 3
[2,] 8 5 2 #rotated 180 degrees
[3,] 7 4 1
Notice that rotating a matrix clockwise, then counterclockwise returns the numbers to their original position, then rotating by 180 is like rotating by 90 twice.
Or combined in a single function (based on Eric Leschinski):
rotate <- function(x, clockwise=T) {
if (clockwise) { t( apply(x, 2, rev))
} else {apply( t(x),2, rev)}
}
Related
I am trying to construct a function f that can rotate a matrix in a clock-wise manner.
The function should looks like this
f <- function(mat, k) {...}
where mat is the matrix, k is the times we perform 90-degree clock-wise rotation. Let's say, k=1 means we rotate the matrix 90 degrees, k=2 means 180 degrees, and so on.
If k > 1, I want to save all those rotated matrices (for i = 1,2,....,k) into a list, such that I can track how the rotation evolves.
Thanks in advance!
I guess you can use rot90 from package pracma to implement the fundamental rotation functionality.
The code below use a recursion method to save all those rotated matrices through 0 to k times of clock-wise rotations
library(pracma)
f <- function(mat, k) {
if (k==0) return(list(mat))
u <- f(mat,(k-1)%%4)
c(u,list(rot90(tail(u,1)[[1]])))
}
Example
Given a matrix mat like below
mat <- matrix(1:12,nrow = 4)
we will see
> f(mat,4)
[[1]]
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
[[2]]
[,1] [,2] [,3] [,4]
[1,] 9 10 11 12
[2,] 5 6 7 8
[3,] 1 2 3 4
[[3]]
[,1] [,2] [,3]
[1,] 12 8 4
[2,] 11 7 3
[3,] 10 6 2
[4,] 9 5 1
[[4]]
[,1] [,2] [,3] [,4]
[1,] 4 3 2 1
[2,] 8 7 6 5
[3,] 12 11 10 9
[[5]]
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
Since the first element of list is the original matrix mat, you can remove it via
f(mat,k)[-1]
I am trying to put a list of matrices together in a list and then do summation inside of each list. Below are the simple example of the codes:
Let's say if I have 4 matrices:
x1 <- matrix(1:9, nrow = 3)
x2 <- matrix(2:10, nrow = 3)
x3 <- matrix(3:11, nrow = 3)
x4 <- matrix(4:12, nrow = 3)
And I want to put them into a list() in a way like this:
[[1]]
[[1]][[1]]
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
[[1]][[2]]
[,1] [,2] [,3]
[1,] 2 5 8
[2,] 3 6 9
[3,] 4 7 10
[[2]]
[,1] [,2] [,3]
[1,] 3 6 9
[2,] 4 7 10
[3,] 5 8 11
[[3]]
[,1] [,2] [,3]
[1,] 4 7 10
[2,] 5 8 11
[3,] 6 9 12
And how do I perform summation of each element inside the list()?
For example, my desired output is as below:
[[1]]
[,1] [,2] [,3]
[1,] 3 9 15
[2,] 5 11 17
[3,] 7 13 19
[[2]]
[,1] [,2] [,3]
[1,] 3 6 9
[2,] 4 7 10
[3,] 5 8 11
[[3]]
[,1] [,2] [,3]
[1,] 4 7 10
[2,] 5 8 11
[3,] 6 9 12
I have tried using list(Reduce(`+`, x)) however it does not work.
Since you want to keep top-level list use lapply :
lapply(x, function(l) if(is.list(l)) Reduce(`+`, l) else l)
#[[1]]
# [,1] [,2] [,3]
#[1,] 3 9 15
#[2,] 5 11 17
#[3,] 7 13 19
#[[2]]
# [,1] [,2] [,3]
#[1,] 3 6 9
#[2,] 4 7 10
#[3,] 5 8 11
#[[3]]
# [,1] [,2] [,3]
#[1,] 4 7 10
#[2,] 5 8 11
#[3,] 6 9 12
A corresponding purrr version of #RonakShah's answer with map_if():
library(purrr)
map_if(x, is.list, reduce, `+`)
# [[1]]
# [,1] [,2] [,3]
# [1,] 3 9 15
# [2,] 5 11 17
# [3,] 7 13 19
#
# [[2]]
# [,1] [,2] [,3]
# [1,] 3 6 9
# [2,] 4 7 10
# [3,] 5 8 11
#
# [[3]]
# [,1] [,2] [,3]
# [1,] 4 7 10
# [2,] 5 8 11
# [3,] 6 9 12
I would like to access an array 3d with a matrix. Here an example of the desired output:
a <- array(1:18, dim=c(3,3,2))
a
, , 1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
, , 2
[,1] [,2] [,3]
[1,] 10 13 16
[2,] 11 14 17
[3,] 12 15 18
b <- array(1:2, dim=c(3,3))
b
[,1] [,2] [,3]
[1,] 1 2 1
[2,] 2 1 2
[3,] 1 2 1
a[b]
[,1] [,2] [,3]
[1,] 1 13 7
[2,] 11 5 17
[3,] 3 15 9
(Should i pass a data frame with 3 columns (indexs + values) instead of a matrix?)
if i do a[b], this is the result:
a[b]
4 11 4
and why?
c <- array(1:2, dim=c(2,2))
a[c]
[1] 1 2 1 2
for b <- array(1:2, dim=c(3,3))
> b
[,1] [,2] [,3]
[1,] 1 2 1
[2,] 2 1 2
[3,] 1 2 1
the indices are read by rows. Thus, as #jogo mentioned, a[b] is actually c(a[1, 2, 1], a[2, 1, 2], a[1, 2, 1])
for C <- array(1:2, dim=c(2,2))
> C
[,1] [,2]
[1,] 1 1
[2,] 2 2
since the dimension of C does not match a (only two out of three fit), in this case a[C] is interpreted as a[c(C)] (thanks to comments from #jogo).
I wanna build an nxm matrix, n< m, and i want each element Mij = i^j
Any ideas? I tried multiplying various vectors etc but i never get the correct result.
n <- 3
m <- 4
outer(seq_len(n), seq_len(m), "^")
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 1
#[2,] 2 4 8 16
#[3,] 3 9 27 81
You can also use sapply:
t(sapply(1:n, `^`, 1:m))
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 1
#[2,] 2 4 8 16
#[3,] 3 9 27 81
Or even faster:
matrix(1:n, ncol=m, nrow=n)^matrix(1:m, ncol=m, nrow=n, byrow=T)
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 1
#[2,] 2 4 8 16
#[3,] 3 9 27 81
I have a list of elements and I want an object that gives me all possible ways of splitting these elements into a given number of groups of the same size.
For example here is my list:
MyElements <- c(1,2,3,4)
And I want all possible combinations of spliting them into 2 groups:
nb.groups <- 2
The answer might for example be of that kind:
[[1]]
[1] 1,2
[2] 3,4
[[2]]
[1] 1,3
[2] 2,4
[[3]]
[1] 2,3
[2] 1,4
I want to avoid the repetition of that kind:
[[1]]
[1] 1,2
[2] 3,4
[[2]]
[1] 3,4
[2] 1,2
Thanks a lot !
Thank you for answering. I think I should give you more informations about what I'm trying to achieve.
the list (or vector because obviously MyElements was a vector) is actually ID numbers for individuals. I want a list of all possible ways of splitting these individuals in a desired number of groups which all have the same size.
If I'm not mistaken the only solution which actually works for the moment is the so-called brute-force-and-dirty solution from Juba. But as Juba said, it gets quickly (way too quickly for my purposes !) unusable.
Thanks again
Following recursive logic allows you to calculate all combinations without repetitions and without the need to calculate all of them first. It works pretty nice, as long as choose(nx-1,ning-1) returns an integer. If it doesn't, calculating the possibilities is a bit ridiculous.
It's a recursive process, so it might take long and it will cause memory trouble when your vectors exceed a certain limit. But then again, dividing a set of 14 elements in 7 groups gives already 135135 unique possibilities. Things get out of hand pretty quick in these kind of things.
The logic in pseudo-something (wouldn't call it pseudocode)
nb = number of groups
ning = number of elements in every group
if(nb == 2)
1. take first element, and add it to every possible
combination of ning-1 elements of x[-1]
2. make the difference for each group defined in step 1 and x
to get the related second group
3. combine the groups from step 2 with the related groups from step 1
if(nb > 2)
1. take first element, and add it to every possible
combination of ning-1 elements of x[-1]
2. to define the other groups belonging to the first groups obtained like this,
apply the algorithm on the other elements of x, but for nb-1 groups
3. combine all possible other groups from step 2
with the related first groups from step 1
Translating this to R gives us :
perm.groups <- function(x,n){
nx <- length(x)
ning <- nx/n
group1 <-
rbind(
matrix(rep(x[1],choose(nx-1,ning-1)),nrow=1),
combn(x[-1],ning-1)
)
ng <- ncol(group1)
if(n > 2){
out <- vector('list',ng)
for(i in seq_len(ng)){
other <- perm.groups(setdiff(x,group1[,i]),n=n-1)
out[[i]] <- lapply(seq_along(other),
function(j) cbind(group1[,i],other[[j]])
)
}
out <- unlist(out,recursive=FALSE)
} else {
other <- lapply(seq_len(ng),function(i)
matrix(setdiff(x,group1[,i]),ncol=1)
)
out <- lapply(seq_len(ng),
function(i) cbind(group1[,i],other[[i]])
)
}
out
}
To show it works :
> perm.groups(1:6,3)
[[1]]
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
[[2]]
[,1] [,2] [,3]
[1,] 1 3 4
[2,] 2 5 6
[[3]]
[,1] [,2] [,3]
[1,] 1 3 4
[2,] 2 6 5
[[4]]
[,1] [,2] [,3]
[1,] 1 2 5
[2,] 3 4 6
[[5]]
[,1] [,2] [,3]
[1,] 1 2 4
[2,] 3 5 6
[[6]]
[,1] [,2] [,3]
[1,] 1 2 4
[2,] 3 6 5
[[7]]
[,1] [,2] [,3]
[1,] 1 2 5
[2,] 4 3 6
[[8]]
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[[9]]
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 6 5
[[10]]
[,1] [,2] [,3]
[1,] 1 2 4
[2,] 5 3 6
[[11]]
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 5 4 6
[[12]]
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 5 6 4
[[13]]
[,1] [,2] [,3]
[1,] 1 2 4
[2,] 6 3 5
[[14]]
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 6 4 5
[[15]]
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 6 5 4
here a solution based on the construction of splitter column.
x <- 1:4
a <- as.data.frame(t(combn(x,length(x)/2))
a$sum <- abs(rowSums(a)-mean(rowSums(a)))
lapply(split(a,a$sum),function(x) if(dim(x)[1]>2)
split(x,1:(dim(x)[1]/2))
else
x)
$`0`
V1 V2 sum
3 1 4 0
4 2 3 0
$`1`
V1 V2 sum
2 1 3 1
5 2 4 1
$`2`
V1 V2 sum
1 1 2 2
6 3 4 2
Here is a brute-force-and-dirty solution, which may work for different number of groups, but you really should test it before use. Moreover, as it uses permn, it will be unusable very fast depending on the size of your vector :
library(combinat)
split.groups <- function(x, nb.groups) {
length.groups <- length(x)/nb.groups
perm <- permn(x)
perm <- lapply(perm, function(v) {
m <- as.data.frame(matrix(v, length.groups, nb.groups))
m <- apply(m,2,sort)
m <- t(m)
m <- m[order(m[,1]),]
rownames(m) <- NULL
m})
unique(perm)
}
Which gives, for example :
R> split.groups(1:4, 2)
[[1]]
[,1] [,2]
[1,] 1 2
[2,] 3 4
[[2]]
[,1] [,2]
[1,] 1 4
[2,] 2 3
[[3]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
Or :
R> split.groups(1:6, 3)
[[1]]
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
[[2]]
[,1] [,2]
[1,] 1 2
[2,] 3 6
[3,] 4 5
[[3]]
[,1] [,2]
[1,] 1 6
[2,] 2 3
[3,] 4 5
[[4]]
[,1] [,2]
[1,] 1 2
[2,] 3 5
[3,] 4 6
[[5]]
[,1] [,2]
[1,] 1 6
[2,] 2 5
[3,] 3 4
[[6]]
[,1] [,2]
[1,] 1 5
[2,] 2 6
[3,] 3 4
[[7]]
[,1] [,2]
[1,] 1 5
[2,] 2 3
[3,] 4 6
[[8]]
[,1] [,2]
[1,] 1 5
[2,] 2 4
[3,] 3 6
[[9]]
[,1] [,2]
[1,] 1 6
[2,] 2 4
[3,] 3 5
[[10]]
[,1] [,2]
[1,] 1 4
[2,] 2 3
[3,] 5 6
[[11]]
[,1] [,2]
[1,] 1 4
[2,] 2 6
[3,] 3 5
[[12]]
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
[[13]]
[,1] [,2]
[1,] 1 3
[2,] 2 5
[3,] 4 6
[[14]]
[,1] [,2]
[1,] 1 3
[2,] 2 6
[3,] 4 5
[[15]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
[3,] 5 6