Let n be a positive integer. We have a matrix B that has n columns, whose entries are integers between 1 and n. The aim is to match the rows of B with the rows of permutations(n), memorizing the indices in a vector v.
For example, let us consider the following. If
permutations(3)=
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 1 3 2
[3,] 2 1 3
[4,] 2 3 1
[5,] 3 1 2
[6,] 3 2 1
and
B=
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 1 2 3
[3,] 3 1 2
[4,] 2 3 1
[5,] 3 1 2
Then the vector v is
1 1 5 4 5
because the first two rows of B are equal to the row number 1 of permutations(3), the third row of B is the row number 5 of permutations(3), and so on.
I tried to apply the command
row.match
but the latter returns the error:
Error in do.call("paste", c(x[, , drop = FALSE], sep = "\r")) :
second argument must be a list
One way is to use match,
match(do.call(paste, data.frame(B)), do.call(paste, data.frame(m1)))
#[1] 1 1 5 4 5
One possible way is to turn your matrices into dataframes and join them:
A = read.table(text = "
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
")
B = read.table(text = "
1 2 3
1 2 3
3 1 2
2 3 1
3 1 2
")
library(dplyr)
A %>%
mutate(row_id = row_number()) %>%
right_join(B) %>%
pull(row_id)
# [1] 1 1 5 4 5
Related
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 have adjacency matrix as below:
> matrix(c(0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0),ncol=4,byrow=T)
[,1] [,2] [,3] [,4]
[1,] 0 1 0 0
[2,] 1 0 1 0
[3,] 0 1 0 1
[4,] 0 0 1 0
Question 1: how can I get the corresponding information like:
2 5 7 10 12 15from R?
Question 2: how can I get the location information of '1's in each row like:
2
1 3
2 4
3
or 2 1 3 2 4 3from R?
Thanks!
Just use which on a logical matrix
which(m1 == 1)
#[1] 2 5 7 10 12 15
If we need the column index in a list
sapply(split(!!m1, col(m1)), which)
Or as a vector
na.omit(na_if(c(t(m1 * col(m1))), 0))
#[1] 2 1 3 2 4 3
data
m1 <- matrix(c(0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0),ncol = 4,byrow = TRUE)
m <- matrix(c(0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0),ncol=4,byrow=T)
mm <- m == 1
which(mm)
#[1] 2 5 7 10 12 15
apply(mm, 1, which)
#[[1]]
#[1] 2
#
#[[2]]
#[1] 1 3
#
#[[3]]
#[1] 2 4
#
#[[4]]
#[1] 3
perhaps also see raster::adjacency
How do I get all possible permutation of a list with duplicate elements?
For example, 2 by with the vector x = x (1,2,2) I want permutation with repetition:
1 1
1 2
1 2
2 1
2 2
2 2
2 1
2 2
2 2
This is easily achieved with one of the many packages for generating permutations with repetition.
library(gtools)
gtools::permutations(3, 2, c(1, 2, 2), set = FALSE, repeats.allowed = TRUE)
[,1] [,2]
[1,] 1 1
[2,] 1 2
[3,] 1 2
[4,] 2 1
[5,] 2 2
[6,] 2 2
[7,] 2 1
[8,] 2 2
[9,] 2 2
library(arrangements)
arrangements::permutations(x = c(1,2,2), k = 2, replace = TRUE)
## output same as above
library(RcppAlgos) ### I am the author
RcppAlgos::permuteGeneral(c(1,2,2), 2, TRUE)
## output same as above
You can use the built-in function rep() as follow :
data.frame(V1 = rep(x, each = length(x)), V2 = rep(x, length(x)))
V1 V2
1 1 1
2 1 2
3 1 2
4 2 1
5 2 2
6 2 2
7 2 1
8 2 2
9 2 2
I'm using r and
I want to fill a 8 lenght dimension vector/table with integer numbers form 1 to 4 with respect to the conditions below:
vector [i]<= vector[i+1]
all integrs should be present
example:
1 1 1 1 2 2 3 4 may be a solution
1 2 1 1 2 3 3 4 isn't a solution to my problem
I am wondering also if there is a way to list all solutions
To get all solutions, reserve four slots for the numbers 1:4 (since every number must appear at least once), and consider all possible length-4 sequences of 1:4 to fill the remaining slots. Sorting and removing duplicates leaves you with 35 non-decreasing sequences:
# The sequences will be the rows of a matrix. First, the 'reserved' slots:
reserved = matrix(1:4, 256, 4, byrow=TRUE)
# Add all combinations of 1:4 to fill the remaining four slots:
result = cbind(reserved,
unname(as.matrix(expand.grid(1:4, 1:4, 1:4, 1:4))) )
# Now simply sort and de-duplicate along rows:
result = t(apply(result, 1, sort))
result = unique(result)
> head(result)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
# [1,] 1 1 1 1 1 2 3 4
# [2,] 1 1 1 1 2 2 3 4
# [3,] 1 1 1 1 2 3 3 4
# [4,] 1 1 1 1 2 3 4 4
# [5,] 1 1 1 1 2 2 3 4
# [6,] 1 1 1 2 2 2 3 4
Okay, sorry I know this sounds unnecessarily confusing. I am basically looking to return a vector of elements equal to the number of rows with each element specifying where in the matrix the specified outcome occurred.
library(gtools)
(A <- permutations(3, 3))
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 1 3 2
[3,] 2 1 3
[4,] 2 3 1
[5,] 3 1 2
[6,] 3 2 1
Using the unknown function foo would return:
foo(A, match=1)
[1] 1 1 2 3 2 3
foo(A, match=2)
[1] 2 3 1 1 3 2
Thank you for any help you can provide!
Use max.col and some indexing of the matrix:
> max.col(A==1)
[1] 1 1 2 3 2 3
> max.col(A==2)
[1] 2 3 1 1 3 2
Try
foo <- function(mat, match=1){
indx <- which(mat==match, arr.ind=TRUE)
indx[order(indx[,1]),2]
}
foo(A, 1)
#[1] 1 1 2 3 2 3
foo(A,2)
#[1] 2 3 1 1 3 2