Reputation: 167
I want to generate a matrix of size n-1 x n such that the i-th column contains all number from 1 to n without containing i, i.e. the first column should contain all numbers from 2 to n, the second should contain 1,3,4,..., the third should contain 1,2,4,... and so on. Any ideas would be most welcomed.
Upvotes: 1
Views: 71
Reputation: 26343
Use combn
(not really random though).
n <- 5
out <- combn(n:1, n - 1)
out
# [,1] [,2] [,3] [,4] [,5]
#[1,] 5 5 5 5 4
#[2,] 4 4 4 3 3
#[3,] 3 3 2 2 2
#[4,] 2 1 1 1 1
Shuffle each column if needed
set.seed(1)
apply(combn(n:1, n - 1), 2, sample)
If you are looking for efficiency, use the solution I posted ;)
library(microbenchmark)
n <- 1000
set.seed(1)
benchmark <- microbenchmark(
akrun = vapply(seq_len(n), function(i) sample(setdiff(seq_len(n), i)), numeric(n-1)),
markus = apply(combn(n:1, n - 1), 2, sample),
A_Stam = create_matrix(n),
times = 30L
)
benchmark
#Unit: milliseconds
# expr min lq mean median uq max neval
# akrun 64.32350 66.99177 73.61685 71.15608 78.79612 104.99161 30
# markus 51.65092 53.01034 59.80802 58.48310 64.76143 78.35348 30
# A_Stam 1331.52882 1379.70371 1470.31044 1407.89861 1548.28011 1896.22913 30
Upvotes: 5
Reputation: 887028
We loop through the sequence of 'n', get the sample
of the sequence except the looped number (setdiff
)
sapply(seq_len(n), function(i) sample(setdiff(seq_len(n), i)))
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] 2 3 1 3 2 2
#[2,] 5 1 5 6 1 5
#[3,] 6 4 6 2 3 4
#[4,] 3 5 4 1 4 1
#[5,] 4 6 2 5 6 3
It can be made a bit more faster if we use vapply
vapply(seq_len(n), function(i) sample(setdiff(seq_len(n), i)), numeric(n-1))
NOTE: The OP mentioned random
matrix in the post
n <- 6
Upvotes: 3
Reputation: 2222
This might not be the most elegant solution, but it works:
create_matrix <- function(n) {
m <- c()
for (i in 1:n) {
new <- setdiff(1:n, i)
m <- c(m, new)
}
matrix(m, ncol = n, byrow = FALSE)
}
create_matrix(4)
#> [,1] [,2] [,3] [,4]
#> [1,] 2 1 1 1
#> [2,] 3 3 2 2
#> [3,] 4 4 4 3
Upvotes: 2