Home > Blockchain >  Select matrix rows that are permutations of a given vector
Select matrix rows that are permutations of a given vector

Time:07-30

I have a matrix X:

     one two three four
 [1,]  1   3   2   4
 [2,]  2   0   1   5
 [3,]  3   2   1   4
 [4,]  4   9   11  19
 [5,]  4   3   2   1

I want to get a new matrix Y which only contains rows that are permutations of "1", "2", "3", "4". That is:

     one two three four
 [1,]  1   3   2   4
 [3,]  3   2   1   4
 [5,]  4   3   2   1

What function or command should I use?

CodePudding user response:

mat <- rbind(
    c(1, 3, 2, 4),
    c(2, 0, 1, 5),
    c(3, 2, 1, 4)
)

ok <- apply(mat, 1L, function(x) setequal(x, c(1, 2, 3, 4)))
mat[ok, ]

CodePudding user response:

Here is another approach:

library(dplyr)
library(stringr)
library(tibble)

new_matrix <- df_matrix %>% 
  as_tibble() %>% 
  filter(if_all(everything(), ~ str_detect(., paste(1:4, collapse = "|")))) %>% 
  as.matrix()
     one two three four
[1,]   1   3     2    4
[2,]   3   2     1    4
[3,]   4   3     2    1

CodePudding user response:

X <- structure(c(1, 2, 3, 4, 4, 3, 0, 2, 9, 3, 2, 1, 1, 11, 2, 4, 5, 4, 19, 1),
               dim = 5:4)

A fully vectorized base R approach:

X[.rowSums(X %in% 1:4, nrow(X), ncol(X)) == 4, ]
#     [,1] [,2] [,3] [,4]
#[1,]    1    3    2    4
#[2,]    3    2    1    4
#[3,]    4    3    2    1

In general, given a target vector v, we do

## keep rows that are permutations of `v`
X[.rowSums(X %in% v, nrow(X), ncol(X)) == length(v), ]

## remove rows that are permutations of `v`
X[.rowSums(X %in% v, nrow(X), ncol(X)) < length(v), ]

CodePudding user response:

Using pure for loop

ans <- data.frame(matrix(NA , ncol = ncol(X)))
r <- 1
for(i in 1:nrow(X)){
    if(all((unique(X[i,]) %in% 1:4) & length(unique(X[i,])) == 4)){
        ans[r,] <- X[i,]
        r <- r   1
    }
}

ans <- as.matrix(ans)
  • output
  X1 X2 X3 X4
1  1  3  2  4
2  3  2  1  4
3  4  3  2  1

  • data
X <- matrix(c(1, 2, 3, 4, 4, 3, 0, 2, 9, 3, 2, 1, 1, 11, 2, 4, 
              5, 4, 19, 1) , ncol = 4)

Another option is using Filter function

t(Filter(\(x) all((unique(x) %in% 1:4) & length(unique(x)) == 4) ,
data.frame(t(X))))
  • Related