【问题标题】:Get the list of items in Venn diagram获取维恩图中的项目列表
【发布时间】:2014-05-09 07:56:00
【问题描述】:

用下面的代码很容易画出维恩图:

library(VennDiagram)

set.seed(1) # For reproducibility of results
xx.1 <- list(A = sample(LETTERS, 15), B = sample(LETTERS, 15), 
             C = sample(LETTERS, 15), D = sample(LETTERS, 15))

venn.diagram(xx.1, filename ="1.tiff", height = 1000, width = 1000)

但是我如何找出每个字段中的项目?例如,我想知道只在 A 中找到的两个字母是什么?

编辑

这是我的解决方案,它并不完美,但可以给出所有的交叉点。

library(reshape)
library(R.utils)

## data
A <- data.frame(names = sample(LETTERS, 15), A = 1)
B <- data.frame(names = sample(LETTERS, 15), B = 1)
C <- data.frame(names = sample(LETTERS, 15), C = 1)
D <- data.frame(names = sample(LETTERS, 15), D = 1)

## a merged data frame.
xx.1 <- list(A = A, B= B, C= C, D = D)
xx.2 <- merge_recurse(xx.1)

## function
ff.vennFourItems <- function(X)
{
    ## get the items from venn diagram; for four sets, there are 15 fields;

    vennItems <- list()
    cate.n <- names(X)[2:5]

    for (i in 1:15)
    {
        xx.b <- intToBin(i)
        ## make it four bits;
        if (nchar(xx.b) != 4)
        {
            xx.b <- paste(paste(rep("0", 4 - nchar(xx.b)), collapse = ""), xx.b, sep ="") 
        }

        xx.b.1 <- unlist(strsplit(xx.b, ""))

        xx.1 <- X

        if(xx.b.1[1] == "0") { xx.1 <- xx.1[is.na(xx.1[, 2]), ] }
        else { xx.1 <-  xx.1[!is.na(xx.1[, 2]), ] }

        if(xx.b.1[2] == "0") { xx.1 <- xx.1[is.na(xx.1[, 3]), ] }
        else { xx.1 <-  xx.1[!is.na(xx.1[, 3]), ] }

        if(xx.b.1[3] == "0") { xx.1 <- xx.1[is.na(xx.1[, 4]), ] }
        else { xx.1 <-  xx.1[!is.na(xx.1[, 4]), ] }

        if(xx.b.1[4] == "0") { xx.1 <- xx.1[is.na(xx.1[, 5]), ] }
        else { xx.1 <-  xx.1[!is.na(xx.1[, 5]), ] }

        chipC <-  paste(paste(cate.n, collapse = "#"), xx.b, sep = "***")

        if (dim(xx.1)[1] == 0) 
        {
            xx.2 <- list(genes = dim(xx.1)[1], chipC = chipC, chipCN = i, detailChipS = xx.1, shortL = data.frame(genes = "noInteraction", cl = i, fullCl = chipC))
        }
        else
        {
            xx.2 <- list(genes = dim(xx.1)[1], chipC = chipC, chipCN = i, detailChipS = xx.1, shortL = data.frame(genes = as.character(xx.1[, 1]), cl = i, fullCl = chipC))
        }
        vennItems <- c(vennItems, list(xx.2))
    }

    vennItems
}

xx.3 <- ff.vennFourItems(xx.2)
str(xx.3)
List of 15
 $ :List of 5
  ..$ genes      : int 1
  ..$ chipC      : chr "A#B#C#D***0001"
  ..$ chipCN     : int 1
  ..$ detailChipS:'data.frame': 1 obs. of  5 variables:
  .. ..$ names: Factor w/ 25 levels "A","B","E","F",..: 25
  .. ..$ A    : num NA
  .. ..$ B    : num NA
  .. ..$ C    : num NA
  .. ..$ D    : num 1
  ..$ shortL     :'data.frame': 1 obs. of  3 variables:
  .. ..$ genes : Factor w/ 1 level "Z": 1
  .. ..$ cl    : int 1
  .. ..$ fullCl: Factor w/ 1 level "A#B#C#D***0001": 1
 $ :List of 5
  ..$ genes      : int 0
  ..$ chipC      : chr "A#B#C#D***0010"
  ..$ chipCN     : int 2

【问题讨论】:

    标签: r venn-diagram


    【解决方案1】:

    看看?intersect?union?setdiff函数提取维恩图的不同字段。

    我为这两个函数创建了一些list 版本,以便更好地获取不同隔间中的元素:

    Intersect <- function (x) {  
      # Multiple set version of intersect
      # x is a list
      if (length(x) == 1) {
        unlist(x)
      } else if (length(x) == 2) {
        intersect(x[[1]], x[[2]])
      } else if (length(x) > 2){
        intersect(x[[1]], Intersect(x[-1]))
      }
    }
    
    Union <- function (x) {  
      # Multiple set version of union
      # x is a list
      if (length(x) == 1) {
        unlist(x)
      } else if (length(x) == 2) {
        union(x[[1]], x[[2]])
      } else if (length(x) > 2) {
        union(x[[1]], Union(x[-1]))
      }
    }
    
    Setdiff <- function (x, y) {
      # Remove the union of the y's from the common x's. 
      # x and y are lists of characters.
      xx <- Intersect(x)
      yy <- Union(y)
      setdiff(xx, yy)
    }
    

    因此,如果我们想查看公共元素(即 A、B、C 和 D 的并集)或 C 和 D 中的元素,而不是您示例中的 A 和 B 中的元素,我们会执行以下操作。

    set.seed(1)
    xx.1 <- list(A = sample(LETTERS, 15), 
                 B = sample(LETTERS, 15), 
                 C = sample(LETTERS, 15), 
                 D = sample(LETTERS, 15))
    Intersect(xx.1)
    #[1] "E" "L"
    Setdiff(xx.1[c("C", "D")], xx.1[c("A", "B")])
    #[1] "O" "P" "K" "H"
    

    希望这会有所帮助!

    编辑:系统获取所有组件

    通过一些(我认为)巧妙地使用combn 函数、索引以及对lapply 的良好理解,我们可以系统地所有元素:

    # Create a list of all the combinations
    combs <- 
      unlist(lapply(1:length(xx.1), 
                    function(j) combn(names(xx.1), j, simplify = FALSE)),
             recursive = FALSE)
    names(combs) <- sapply(combs, function(i) paste0(i, collapse = ""))
    str(combs)
    #List of 15
    # $ A   : chr "A"
    # $ B   : chr "B"
    # $ C   : chr "C"
    # $ D   : chr "D"
    # $ AB  : chr [1:2] "A" "B"
    # $ AC  : chr [1:2] "A" "C"
    # $ AD  : chr [1:2] "A" "D"
    # $ BC  : chr [1:2] "B" "C"
    # $ BD  : chr [1:2] "B" "D"
    # $ CD  : chr [1:2] "C" "D"
    # $ ABC : chr [1:3] "A" "B" "C"
    # $ ABD : chr [1:3] "A" "B" "D"
    # $ ACD : chr [1:3] "A" "C" "D"
    # $ BCD : chr [1:3] "B" "C" "D"
    # $ ABCD: chr [1:4] "A" "B" "C" "D"
    
    # "A" means "everything in A minus all others"
    # "A", "B" means "everything in "A" and "B" minus all others" and so on
    elements <- 
      lapply(combs, function(i) Setdiff(xx.1[i], xx.1[setdiff(names(xx.1), i)]))
    
    n.elements <- sapply(elements, length)
    print(n.elements)
    #   A    B    C    D   AB   AC   AD   BC   BD   CD  ABC  ABD  ACD  BCD ABCD 
    #   2    2    0    0    1    2    2    0    3    4    4    1    1    2    2 
    

    【讨论】:

    • 添加联合结果会很棒! (只是为了获得完整的示例)我在更复杂的过程中或多或少做了相同的事情,但是您的解决方案既简单又出色!
    • @AEBilgrau,谢谢。是一种系统地获取所有 15 个字段的方法吗?
    • @AEBilgrau,真是太棒了!
    • @Llopis 我也添加了递归Union。好建议,谢谢。
    • @al-ash 的回答似乎更易于使用。
    【解决方案2】:

    您还可以使用gplots 包中的venn 来获取维恩图('ItemsList')每个部分中的项目列表。鉴于您的列表 xx.1,它应该是:

    ItemsList <- venn(xx.1, show.plot = FALSE)
    

    ItemsList 包含:

    1. 所有图表部分的矩阵和这些部分中的项目计数和
    2. 每个维恩图部分中的项目列表。

    获取计数:

    lengths(attributes(ItemsList)$intersections)
    # A       B     A:B     A:C     A:D     B:D     C:D   A:B:C   A:B:D   A:C:D   B:C:D A:B:C:D 
    # 2       2       1       2       2       3       4       4       1       1       2       2
    

    【讨论】:

      【解决方案3】:

      VennDiagram包中,有一个叫做“calculate.overlap”的函数。

      overlap <- calculate.overlap(xx.1)
      

      重叠就是你想要的:

      $a6
      [1] "C"
      
      $a12
      [1] "Z" "D" "R"
      
      $a11
      [1] "Y" "O" "V"
      
      $a5
      [1] "X" "B"
      
      $a7
      [1] "H" "F" "P" "S"
      
      $a15
      [1] "I"
      
      $a4
      [1] "L" "K" "G"
      
      $a10
      [1] "W" "J"
      
      $a13
      [1] "U"
      
      $a8
      character(0)
      
      $a2
      character(0)
      
      $a9
      character(0)
      
      $a14
      [1] "N" "M"
      
      $a1
      [1] "E"
      
      $a3
      [1] "Q" "A" "T"
      

      【讨论】:

      • 获取交叉点的名称似乎不可行,即 a1 的含义。
      • 很好的解决方案——但是你怎么看这个?例如,$a5、$a10 和 $a14 都有 3 个字母,对应于维恩河上 3 个不同区域的交点。如何确定这 3 个属于哪些重叠?
      猜你喜欢
      • 1970-01-01
      • 2023-01-14
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 2013-01-24
      • 2018-12-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多