I have a matrix M given by the following:
M <- matrix(1:6, nrow=2, byrow=TRUE)
1 2 3
4 5 6
and I wish to generate all possible permutations for this matrix as a list. After reading Generating all distinct permutations of a list in R, I've tried using
library(combinat)
permn(M)
but this gives the me all the permutations as a single row, and not the 2 x 3 matrix I had originally.
So what I get is something like
[[1]]
[1] 1 4 2 5 3 6
[[2]]
[1] 1 4 2 5 6 3
[[3]]
[1] 1 4 2 6 5 3
...
[[720]]
[1] 4 1 2 5 3 6
But what I want is to keep the first and second rows distinct from each other so it would be a list that looks more like the following:
[[1]]
1 2 3
4 5 6
[[2]]
1 3 2
4 5 6
[[3]]
2 3 1
5 4 6
...
until I get all possible combinations of M. Is there a way to do this in R?
Thank you!
How about this, using expand.grid to get all the possibilities of combinations?
M <- matrix(1:6, nrow=2, byrow=TRUE)
pcM <- permn(ncol(M))
expP <- expand.grid(1:length(pcM), 1:length(pcM))
Map(
function(a,b) rbind( M[1, pcM[[a]]], M[2, pcM[[a]]] ),
expP[,1],
expP[,2]
)
#[[1]]
# [,1] [,2] [,3]
#[1,] 1 2 3
#[2,] 4 5 6
#
#...
#
#[[36]]
# [,1] [,2] [,3]
#[1,] 2 1 3
#[2,] 5 4 6
Related
If there were a matrix, example:
m <- matrix(c(1:4), nrow = 4, ncol=4)
how would I go about multiplying only the odd rows by an arbitrary scalar while still keeping the even rows in the same place and the same value?
In this example, the matrix with only odd rows being multiplied by two would become:
1 1 1 1 2 2 2 2
2 2 2 2 2 2 2 2
3 3 3 3 ----> 6 6 6 6
4 4 4 4 4 4 4 4
You can pass bool vector to matrix, and if it divisible with number of rows r will replicate it.
mat <- matrix(1:4,4,4)
mat[c(TRUE,FALSE),] <- mat[c(TRUE,FALSE),] * 2
[,1] [,2] [,3] [,4]
[1,] 2 2 2 2
[2,] 2 2 2 2
[3,] 6 6 6 6
[4,] 4 4 4 4
Here is a base R code using diag() + rep()
diag(rep(c(2,1),nrow(mat)/2))%*% mat
such that
> diag(rep(c(2,1),nrow(mat)/2))%*% mat
[,1] [,2] [,3] [,4]
[1,] 2 2 2 2
[2,] 2 2 2 2
[3,] 6 6 6 6
[4,] 4 4 4 4
I'd like to return a grid with unique rows from a sequence vector. I'm looking for a general solution so I can pass any number of sequences in a vector. I don't know the terminology for this, so how can I do this?
Example
num <- 3
v <- c(seq(1, num, 1))
Desired Output
1 2 3
2 3 1
3 1 2
Second and third column can be switched:
1 3 2
2 1 3
3 2 1
I tried manipulating expand.grid() but it requires sorting and filtering which seems excessive.
We can use permn from combinat package which generates all possible permutations of v and then select top num of them using head
head(as.data.frame(do.call(rbind, combinat::permn(v))), num)
# V1 V2 V3
#1 1 2 3
#2 1 3 2
#3 3 1 2
We can also use sample to select any num rows instead of first num rows using head.
where
combinat::permn(v) #gives
#[[1]]
#[1] 1 2 3
#[[2]]
#[1] 1 3 2
#[[3]]
#[1] 3 1 2
#[[4]]
#[1] 3 2 1
#[[5]]
#[1] 2 3 1
#[[6]]
#[1] 2 1 3
Here's one solution (column order differs but the idea holds):
n = 3
sweep(replicate(n, 1:n), 2, 1:n, "+") %% n + 1
[,1] [,2] [,3]
[1,] 3 1 2
[2,] 1 2 3
[3,] 2 3 1
Explanation:
replicate will first create a matrix where each row is 1:n:
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 2 2 2
[3,] 3 3 3
I then use the sweep function to add 1 to column 1, 2 to column 2, 3 to column 3:
[,1] [,2] [,3]
[1,] 2 3 4
[2,] 3 4 5
[3,] 4 5 6
At this point, you can do a modulo on the matrix and then add 1 to arrive at the desired matrix.
Edit: If you need to have the same column order as you had above, can do
(sweep(replicate(n, 1:n), 2, 1:n, "+") + 1) %% n + 1
Another base R option
t(sapply(1:length(v), function(i) rep(v, 2)[i:(i+2)]))
# [,1] [,2] [,3]
#[1,] 1 2 3
#[2,] 2 3 1
#[3,] 3 1 2
Explanation: We cyclically permute v and store the vectors as column vectors in a matrix.
For general v (of length length(v)) this becomes
t(sapply(1:length(v), function(i) rep(v, 2)[i:(i + length(v) - 1)]))
I am looking for a fast way to convert a list into a matrix with an additional column containing a repeating 1:5 pattern. For instance, the list mat looks like this. The list and the repeating pattern can get to thousands of values in length and so a fast approach would be ideal.
I can convert the list to a matrix using melt (may not be ideal for large matrices though), however, I am having trouble getting the repeating pattern to work.
The matrix looks like this
mat
[[1]]
[1] 5
[[2]]
[1] 1 4 5
[[3]]
[1] 3 1
[[4]]
[1] 4 6 5 3
The output should contain the values of the list as well as an index column containing a 1:5 repeating pattern depending on the length of each index in the list. For instance, mat[[4]] contains 4 values, therefore the index column should contain a values 1:4
output
[,1] [,2]
5 1
1 1
4 2
5 3
3 1
1 2
4 1
6 2
5 3
3 4
mat <- list(5, c(1,4,5), c(3,1), c(4,6,5,3)) ## your example data
We can use basic operations:
cbind( unlist(mat), sequence(lengths(mat)) )
# [,1] [,2]
# [1,] 5 1
# [2,] 1 1
# [3,] 4 2
# [4,] 5 3
# [5,] 3 1
# [6,] 1 2
# [7,] 4 1
# [8,] 6 2
# [9,] 5 3
#[10,] 3 4
Alternatively,
cbind( unlist(mat), unlist(lapply(mat, seq_along)) )
Here is another option with Map. We get the sequence of each list element with lapply, cbind the corresponding elements of list using Map and rbind it.
do.call(rbind, Map(cbind, mat, lapply(mat, seq_along)))
# [,1] [,2]
#[1,] 5 1
#[2,] 1 1
#[3,] 4 2
#[4,] 5 3
#[5,] 3 1
#[6,] 1 2
#[7,] 4 1
#[8,] 6 2
#[9,] 5 3
#[10,] 3 4
Or with data.table, we melt the list to a 2 column data.frame, convert it to data.table with setDT and assign (:=) the sequence of 'L1' to 'L1' after grouping by 'L1'
library(data.table)
setDT(melt(mat))[, L1 := seq_len(.N), L1][]
# value L1
# 1: 5 1
# 2: 1 1
# 3: 4 2
# 4: 5 3
# 5: 3 1
# 6: 1 2
# 7: 4 1
# 8: 6 2
# 9: 5 3
#10: 3 4
I have an m x n matrix that looks like this:
1 2 3
4 5 6
What is the fastest way to get all possible combinations by row? In this case, that would be c(1,4), c(1,5), c(1,6), c(2,4), c(2,5) ... c(3,5), c(3,6)
How do I solve this using a vectorized approach? In general an m x n matrix would have n^m such combinations.
You can use the expand.grid function to get all combinations of the elements in each row, building a list of rows using split as shown here and passing each element of that list to expand.grid with the do.call function:
(m <- rbind(1:3, 4:6))
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 4 5 6
do.call(expand.grid, split(m, rep(1:nrow(m), ncol(m))))
# 1 2
# 1 1 4
# 2 2 4
# 3 3 4
# 4 1 5
# 5 2 5
# 6 3 5
# 7 1 6
# 8 2 6
# 9 3 6
Here's an example with a 3 x 2 matrix instead of a 2 x 3 matrix:
(m <- matrix(1:6, nrow=3))
# [,1] [,2]
# [1,] 1 4
# [2,] 2 5
# [3,] 3 6
do.call(expand.grid, split(m, rep(1:nrow(m), ncol(m))))
# 1 2 3
# 1 1 2 3
# 2 4 2 3
# 3 1 5 3
# 4 4 5 3
# 5 1 2 6
# 6 4 2 6
# 7 1 5 6
# 8 4 5 6
I am trying to create a matrix by drawing random block rows from another matrix. I have managed to do so with a loop.
set.seed(1)
a_matrix <- matrix(1:10,10,5) # the matrix with original sample
b_matrix <- matrix(NA,10, 5) # a matrix to store the bootstrap sample
S2<- seq(from =1 , to = 10, by =2) #[1] 1 3 5 7 9
m <- 2 # block size of m
for (r in S2){ start_point<-sample(1:(nrow(a_matrix)-1), 1, replace=T)
#randomly choose a number 1 to length of a_matrix -1
b_block <- a_matrix[start_point:(start_point+(m-1)), 1:ncol(a_matrix)]
# randomly select blocks from matrix a
b_matrix[r,]<-as.matrix((b_block)[1,])
b_matrix[(r+1),]<-as.matrix((b_block)[2,]) # put the blocks into matrix b
}
b_matrix
#we now have a b_matrix that is made of random blocks (size m=2)
#of the original a_matrix
The loop method works but it is clearly not very efficient and it is not possible to extend it to other block size (for e.g. having a blocksize of 3) .What is a cleaner and expandable approach ? Thanks in advance
Here I tried to clean it up a bit and generalize the use of m:
random_block_sample <- function(a_matrix, m = 2L) {
N <- nrow(a_matrix)
stopifnot(m <= N)
n <- ceiling(N / m)
s <- sample(N - m + 1L, n, TRUE) # start_point
i <- unlist(lapply(s, seq, length.out = m))
b_matrix <- a_matrix[i, , drop = FALSE]
head(b_matrix, N)
}
set.seed(1L)
random_block_sample(a_matrix, m = 2L)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 3 3 3 3 3
# [2,] 4 4 4 4 4
# [3,] 4 4 4 4 4
# [4,] 5 5 5 5 5
# [5,] 6 6 6 6 6
# [6,] 7 7 7 7 7
# [7,] 9 9 9 9 9
# [8,] 10 10 10 10 10
# [9,] 2 2 2 2 2
# [10,] 3 3 3 3 3
set.seed(1L)
random_block_sample(a_matrix, m = 5L)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 2 2 2 2 2
# [2,] 3 3 3 3 3
# [3,] 4 4 4 4 4
# [4,] 5 5 5 5 5
# [5,] 6 6 6 6 6
# [6,] 3 3 3 3 3
# [7,] 4 4 4 4 4
# [8,] 5 5 5 5 5
# [9,] 6 6 6 6 6
# [10,] 7 7 7 7 7