在%运算符中泛化R%以匹配元组

ASV*_*ASV 8 tuples r operators match

前几天我花了一些时间寻找一种方法来检查行向量是否包含在R中的某些行向量中.基本上,我想概括%in%运算符以匹配元组而不是向量中的每个条目.例如,我想:

row.vec = c("A", 3)
row.vec
# [1] "A" "3"

data.set = rbind(c("A",1),c("B",3),c("C",2))
data.set
#      [,1] [,2]
# [1,] "A"  "1" 
# [2,] "B"  "3" 
# [3,] "C"  "2" 

row.vec %tuple.in% data.set
# [1] FALSE
Run Code Online (Sandbox Code Playgroud)

对于我的伪造运算符,%tuple.in%因为行向量c("A",3)不是data.set中的行向量.使用%in%运算符给出:

row.vec %in% data.set
# [1] TRUE TRUE
Run Code Online (Sandbox Code Playgroud)

因为"A"和3都在data.set,这不是我想要的.

我有两个问题.首先,对此有什么好的解决方案吗?

其次,由于我找不到它们(即使它们存在),我试着编写自己的函数来完成它.它适用于行向量的输入矩阵,但我想知道是否有任何专家提出了改进:

is.tuple.in <- function(matrix1, matrix2){

     # Apply rbind() so that matrix1 has columns even if it is a row vector.
     matrix1 = rbind(matrix1)

     if(ncol(matrix1) != ncol(matrix2)){ 
      stop("Matrices must have the same number of columns.") }

     # Now check for the first row and handle other rows recursively
     row.vec = matrix1[1,]
     tuple.found = FALSE
     for(i in 1:nrow(matrix2)){
          # If we find a match, then this row exists in matrix 2 and we can break the loop
          if(all(row.vec == matrix2[i,])){
               tuple.found = TRUE
               break
          }
     }

     # If there are more rows to be checked, use a recursive call
     if(nrow(matrix1) > 1){
          return(c(tuple.found, is.tuple.in(matrix1[2:nrow(matrix1),],matrix2)))
     } else {
          return(tuple.found)
     }
}
Run Code Online (Sandbox Code Playgroud)

我发现有几个问题,我不确定如何解决.首先,我希望在函数开始时清楚基本情况.我没有设法做到这一点,因为我传递matrix1[2:nrow(matrix1),]了递归调用,如果matrix1有一行则会产生错误.因此matrix1,我没有得到一个空的情况,而是在最后决定是否需要更多的迭代.

其次,我认为rbind()在开始时的使用是草率的,但我需要它的时候matrix1已经减少到一排.不使用rbind(),ncol(matrix1)在1行情况下产生错误.我认为我的麻烦与缺乏有关R数据类型的知识有关.

任何帮助,将不胜感激.

raw*_*awr 5

我想知道你是否让它变得比它复杂一点.例如,

set.seed(1618)
vec <- c(1,3)
mat <- matrix(rpois(1000,3), ncol = 2)
rownames(mat) <- 1:nrow(mat)


mat[sapply(1:nrow(mat), function(x) all(vec %in% mat[x, ])), ]

# gives me this
#     [,1] [,2]
# 6      3    1
# 38     3    1
# 39     3    1
# 85     1    3
# 88     1    3
# 89     1    3
# 95     3    1
# 113    1    3
# ...
Run Code Online (Sandbox Code Playgroud)

如果您关心订单,可以进一步对此进行子集化,或者您可以稍微修改该函数:

mat[sapply(1:nrow(mat), function(x) 
  all(paste(vec, collapse = '') %in% paste(mat[x, ], collapse = ''))), ]

#      [,1] [,2]
# 85     1    3
# 88     1    3
# 89     1    3
# 113    1    3
# 133    1    3
# 139    1    3
# 187    1    3
# ...
Run Code Online (Sandbox Code Playgroud)

另一个带有更长矢量的例子

set.seed(1618)
vec <- c(1,4,5,2)
mat <- matrix(rpois(10000, 3), ncol = 4)
rownames(mat) <- 1:nrow(mat)

mat[sapply(1:nrow(mat), function(x) all(vec %in% mat[x, ])), ]

#      [,1] [,2] [,3] [,4]
# 57      2    5    1    4
# 147     1    5    2    4
# 279     1    2    5    4
# 303     1    5    2    4
# 437     1    5    4    2
# 443     1    4    5    2
# 580     5    4    2    1
# ...
Run Code Online (Sandbox Code Playgroud)

我看到一对匹配:

mat[sapply(1:nrow(mat), function(x) 
  all(paste(vec, collapse = '') %in% paste(mat[x, ], collapse = ''))), ]

#      [,1] [,2] [,3] [,4]
# 443     1    4    5    2
# 901     1    4    5    2
# 1047    1    4    5    2
Run Code Online (Sandbox Code Playgroud)

但只有三个

对于你的单排案例:

vec <- c(1,4,5,2)
mat <- matrix(c(1,4,5,2), ncol = 4)
rownames(mat) <- 1:nrow(mat)

mat[sapply(1:nrow(mat), function(x) 
  all(paste(vec, collapse = '') %in% paste(mat[x, ], collapse = ''))), ]

# [1] 1 4 5 2
Run Code Online (Sandbox Code Playgroud)

这是一个带有上述代码的简单函数

is.tuplein <- function(vec, mat, exact = TRUE) {  
  rownames(mat) <- 1:nrow(mat)
  if (exact) 
    tmp <- mat[sapply(1:nrow(mat), function(x) 
      all(paste(vec, collapse = '') %in% paste(mat[x, ], collapse = ''))), ]
  else tmp <- mat[sapply(1:nrow(mat), function(x) all(vec %in% mat[x, ])), ]
  return(tmp)
}

is.tuplein(vec = vec, mat = mat)
# [1] 1 4 5 2
Run Code Online (Sandbox Code Playgroud)

似乎工作,所以让我们自己的%in%运营商:

`%tuple%` <- function(x, y) is.tuplein(vec = x, mat = y, exact = TRUE)
`%tuple1%` <- function(x, y) is.tuplein(vec = x, mat = y, exact = FALSE)
Run Code Online (Sandbox Code Playgroud)

并试试她

set.seed(1618)
c(1,2,3) %tuple% matrix(rpois(1002,3), ncol = 3)

#     [,1] [,2] [,3]
# 133    1    2    3
# 190    1    2    3
# 321    1    2    3

set.seed(1618)
c(1,2,3) %tuple1% matrix(rpois(1002,3), ncol = 3)

#     [,1] [,2] [,3]
# 48     2    3    1
# 64     2    3    1
# 71     1    3    2
# 73     3    1    2
# 108    3    1    2
# 112    1    3    2
# 133    1    2    3
# 166    2    1    3
Run Code Online (Sandbox Code Playgroud)