如何检查一个向量是否是列表中另一个向量的子集(subset)

4

我浏览了类似的帖子并尝试过它们,但仍无法解决我的问题。

我有一个向量列表,如下所示:

y2 <- c(0,0,NA,0,0,0,0)
y <- c(0,0,0,NA,NA,0)
x <- c(0,0,0,0)
li <-list(y2,y,x)

我正在尝试从列表
  • 中删除向量,如果一个精确的向量是另一个向量的子集。
    例如,在我的情况下,我应该得到y2和y作为结果,并且从列表中删除x,因为x是y2的精确子集。
    我编写了以下脚本,但它只给出y2作为结果,而忽略了y:
    UniquePath <- function(PATHS)
    {
      for(j in length(PATHS):1)
      {
        for(i in 1:length(PATHS))
        {
          if((i!=j)&(isTRUE(all(is.element(PATHS[[j]],PATHS[[i]])))))
          {
            PATHS<-PATHS[-j]
            break
          }
          else
          {
            next
          }
        }
      }
      return(PATHS)
    }
    

  • 你的意思是因为 0x 中出现了四次,那么 0y 或者 y2 中也应该有四次出现吗? - Heikki
    @Heikki,是的。因为x由四个零组成,而且y2也由4个零组成,所以我们丢弃x向量。 - Ester Silva
    向量的顺序在列表中是否重要? - Heikki
    @EsterSilva 你能否评论一下以下数据的结果应该是什么:x <- c(0,0,0,0); y <- c(0,NA,0,0,0); y2 <- c(NA,NA,0,0,0,0); l <- list(x,y,y2)(这里的 xy子集yy2子集)? - storaged
    3个回答

    5

    我的方法是(假设你的字符串中没有“;”)

    # make li unique
    li <- unique(li)
    # collapse each unique list element to a length-1 string surrounded by ";" 
    x <- sapply(li, function(x) paste0(";", paste(x, collapse = ";"), ";"))
    # check each element, if this is found somewhere in any other element
    li[sapply(seq_along(x), function(i) !any(grepl(x[i], x[-i], fixed = TRUE)))]
    # [[1]]
    # [1]  0  0 NA  0  0  0  0
    # 
    # [[2]]
    # [1]  0  0  0 NA NA  0
    

    然而,看起来OP应该提供一个更大的例子,并澄清其他答案评论中提出的一些问题。
    注意:在这个答案中,我定义x是y的子集,当且仅当x的确切序列在y中出现,没有任何其他元素插入其中。这是我理解这个问题的方式。

    我发现了相同的答案,但太晚了。我会删除我的回答。我只是认为你可以把第二行缩短一点,它仍然可以工作:lapply(li,function(x)toString(x)) - denis
    @denis,我使用这两个粘贴的原因是有道理的。如果你只使用toString,结果可能会出错,因为我们只是部分匹配字符串。 - talat
    我可能理解有误(抱歉!),但是为什么类似这样的东西不起作用:temp <- sapply(li, paste0, collapse = "") li[sapply(temp, function(x) sum(grepl(x, temp)) == 1)] - User2321
    1
    考虑一些不同于0的数字。然后,使用collapse = ""是没有意义的,因为您无法区分“010”条目是“0,1,0”还是“0,10”,例如。这只是该代码的一个问题。@User2321 - talat

    0

    我认为这可能是你正在寻找的。

    uniquePath <- function(l){
      idxs <- 1:length(l)
      tmp <- lapply(l, table, useNA='always')
      l2 <- lapply(idxs, function(i){
        res <- l[[i]]
        for(j in idxs[-i]){
          if ( all(res %in% l[[j]]) & all(tmp[[i]] <= tmp[[j]])){ 
            res <- NULL; break 
          }
        }
        res
      })
      Filter(Negate(is.null), l2)
    }
    

    一些例子:
    y2 <- c(0,0,NA,0,0,0,0); y <- c(0,0,0,NA,NA,0); x <- c(0,0,0,0)
    li <-list(y2 = y2,y = y,x = x)
    ## This is your example, where x is subset of both y and y2
    uniquePath(li)
    # [[1]]
    # [1]  0  0 NA  0  0  0  0
    #
    # [[2]]
    # [1]  0  0  0 NA NA  0
    
    x <- c(0,0,0,0); y <- c(0,NA,0,0,0); y2 <- c(NA,NA,0,0,0,0)
    l <- list(x,y,y2)
    ## Here x is a subset of y and y is a subset of y2
    uniquePath(l)
    # [[1]]
    # [1] NA NA  0  0  0  0
    

    0
    以下使用递归函数怎么样?
    # Your sample data
    y2 <- c(0,0,NA,0,0,0,0)
    y <- c(0,0,0,NA,NA,0)
    x <- c(0,0,0,0)
    li <-list(y2 = y2,y = y,x = x)
    

    我定义了一个递归函数collapseList,如果列表条目是其他列表条目的有序子集,则递归地删除它们。
    # Recursive function to collapse entries
    collapseList <- function(lst) {
        s <- sapply(lst, paste, collapse = "");
        if (sum(grepl(s[1], s)) > 1) {
            lst <- lst[-1];
            collapseList(lst);
        }
        else lst;
    }
    

    根据您的示例列表输出:

    # Order list by number of list elements
    li <- li[order(sapply(li, length))];
    
    li <- collapseList(li);
    li;
    #$y
    #[1]  0  0  0 NA NA  0
    #
    #$y2
    #[1]  0  0 NA  0  0  0  0
    

    示例@存储

    li <- list(
        x = c(0,0,0,0), 
        y = c(0,NA,0,0,0), 
        y2 = c(NA,NA,0,0,0,0));
    
    li <- li[order(sapply(li, length))];
    collapseList(li);
    #$y
    #[1]  0 NA  0  0  0
    #
    #$y2
    #[1] NA NA  0  0  0  0
    

    据我所知,这个问题不是所有情况下都适用。请检查:x <- c(0,0,0,0); y <- c(0,NA,0,0,0); y2 <- c(NA,NA,0,0,0,0); l <- list(x,y,y2) 输出结果是一个包含两个元素的列表,其中一个元素是另一个元素的子集。 - storaged
    @storaged 很可能是我误解了。但是对于你给出的例子,我最终得到了两个向量的列表(yy2),而x被删除了。这似乎符合(我认为)OP想要的。yy2不是彼此的子集。 - Maurits Evers
    @storaged 我想我明白你的意思了。我理解OP将子集定义为完整的向量(如x = c(0, 0, 0, 0)),它是较大向量(如y2 = c(0, 0, NA, 0, 0, 0, 0))的一部分。在这种情况下,从列表中删除较小的向量。也许OP可以澄清一下... - Maurits Evers
    @storaged 是的,我同意。 - Maurits Evers
    1
    @storaged 也许你可以向原帖作者提供你的示例,并要求他澄清预期输出。 - Maurits Evers
    显示剩余3条评论

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接