【问题标题】:How often observations occur together in rows R观察值在 R 行中一起出现的频率
【发布时间】:2019-12-28 08:40:44
【问题描述】:

我有一个可与以下数据相媲美的数据框:

V1 V2 V3 V4 V5 V6 V7
 A B  C  D  NA NA NA
 A E  F  NA NA NA NA
 D A  C  B  F  E  NA
 A E  NA NA NA NA NA

每一行都是一个病人,数据框中的每个字母代表一个特定的诊断。

我想了解特定诊断一起发生的频率, 例如诊断 A 与诊断 E 逐行出现多少次? (三次)。

I am hoping to produce a matrix like this:
  A B C D E F
A 0 2 2 2 3 2
B 2 0 2
C 2 2 0 etc etc
D 2
E 3
F 2

(I have not completely filled it out)

它本质上是一个邻接矩阵,只是观察值不需要直接相邻,它们只需要在同一行上。

然后我会从这里产生一个和弦图。

感谢您的帮助!

【问题讨论】:

    标签: r igraph plyr frequency-analysis chord-diagram


    【解决方案1】:

    这是一种替代方法,它使用 自连接 为每位患者创建可能的诊断组合:

    library(data.table)
    library(magrittr)
    co_occ_mat <- function(DT) {
      DT[, id := .I] %>% 
        melt("id", na.rm = TRUE, value.name = "diagnosis") %>% 
        unique(by = c("id", "diagnosis")) %>% 
        .[., on = .(id), allow.cartesian = TRUE] %>% 
        .[diagnosis != i.diagnosis] %>% 
        dcast(diagnosis ~ i.diagnosis, length)
    } 
    

    使用 OP 的样本数据,co_occ_mat() 返回

    fread("V1 V2 V3 V4 V5 V6 V7
     A B  C  D  NA NA NA
     A E  F  NA NA NA NA
     D A  C  B  F  E  NA
     A E  NA NA NA NA NA") %>% 
      co_occ_mat()
    
       diagnosis A B C D E F
    1:         A 0 2 2 2 3 2
    2:         B 2 0 2 2 1 1
    3:         C 2 2 0 2 1 1
    4:         D 2 2 2 0 1 1
    5:         E 3 1 1 1 0 2
    6:         F 2 1 1 1 2 0
    

    符合OP的预期结果。

    co_occ_mat()中的步骤是:

    1. 为每一行添加一个id 列,即患者
    2. 重塑为长格式
    3. 如果患者的诊断报告不止一次,请删除所有重复项
    4. 通过笛卡尔自联接为每个id 创建诊断对
    5. 删除两个诊断相同的对的琐碎案例
    6. 通过重塑为宽格式并对患者进行计数来创建共现矩阵

    使用来自Roman's answer的数据

    RNGversion("3.6.0")
    set.seed(357)
    matrix(sample(LETTERS[1:15], size = 80, replace = TRUE), nrow = 8) %>% 
      as.data.table() %T>% print() %>% 
      co_occ_mat()
    
       V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
    1:  G  F  M  N  D  G  N  H  K   K
    2:  H  I  C  K  H  E  H  E  I   G
    3:  G  C  C  L  N  F  M  K  C   E
    4:  A  K  G  O  I  C  C  B  O   I
    5:  K  O  E  B  M  O  F  C  L   N
    6:  D  H  K  H  I  N  B  F  A   H
    7:  J  N  D  J  L  K  M  A  O   O
    8:  J  D  I  M  O  H  N  O  H   H
    

    我们得到

        diagnosis A B C D E F G H I J K L M N O
     1:         A 0 2 1 2 0 1 1 1 2 1 3 1 1 2 2
     2:         B 2 0 2 1 1 2 1 1 2 0 3 1 1 2 2
     3:         C 1 2 0 0 3 2 3 1 2 0 4 2 2 2 2
     4:         D 2 1 0 0 0 2 1 3 2 2 3 1 3 4 2
     5:         E 0 1 3 0 0 2 2 1 1 0 3 2 2 2 1
     6:         F 1 2 2 2 2 0 2 2 1 0 4 2 3 4 1
     7:         G 1 1 3 1 2 2 0 2 2 0 4 1 2 2 1
     8:         H 1 1 1 3 1 2 2 0 3 1 3 0 2 3 1
     9:         I 2 2 2 2 1 1 2 3 0 1 3 0 1 2 2
    10:         J 1 0 0 2 0 0 0 1 1 0 1 1 2 2 2
    11:         K 3 3 4 3 3 4 4 3 3 1 0 3 4 5 3
    12:         L 1 1 2 1 2 2 1 0 0 1 3 0 3 3 2
    13:         M 1 1 2 3 2 3 2 2 1 2 4 3 0 5 3
    14:         N 2 2 2 4 2 4 2 3 2 2 5 3 5 0 3
    15:         O 2 2 2 2 1 1 1 1 2 2 3 2 3 3 0
    

    出于某种我还不明白的原因,需要在set.seed(357) 之前调用RNGversion("3.6.0") 以重现罗马的随机数。

    请注意,此测试用例包含每个患者的重复诊断,例如,第 1 行中的 K

    【讨论】:

      【解决方案2】:

      我认为手工构建它会很有趣。该算法非常简单。对于每个患者,找出同时发生的诊断并将其写入上三角矩阵。

      set.seed(357)
      xy <- matrix(sample(LETTERS[1:15], size = 80, replace = TRUE), nrow = 8)
      
      > head(xy)
           [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
      [1,] "G"  "F"  "M"  "N"  "D"  "G"  "N"  "H"  "K"  "K"  
      [2,] "H"  "I"  "C"  "K"  "H"  "E"  "H"  "E"  "I"  "G"  
      [3,] "G"  "C"  "C"  "L"  "N"  "F"  "M"  "K"  "C"  "E"  
      [4,] "A"  "K"  "G"  "O"  "I"  "C"  "C"  "B"  "O"  "I"  
      [5,] "K"  "O"  "E"  "B"  "M"  "O"  "F"  "C"  "L"  "N"  
      [6,] "D"  "H"  "K"  "H"  "I"  "N"  "B"  "F"  "A"  "H" 
      
      # Find all unique diagnoses.
      all.diagnoses <- unique(as.vector(xy))
      all.diagnoses <- sort(as.character(all.diagnoses))
      
      # This is a way of creating an empty matrix.
      out <- matrix(rep(NA, length(all.diagnoses)^2), nrow = length(all.diagnoses),
                    dimnames = list(all.diagnoses, all.diagnoses))
      
      for (i in 1:nrow(xy)) {
        combinations <- combn(unique(xy[i, ]), m = 2, simplify = FALSE)
        for (j in 1:length(combinations)) {
          # Add occurrence of each combination to the corresponding combination.
          com <- sort(combinations[[j]])
          out[com[1], com[2]]  <- sum(out[com[1], com[2]], 1, na.rm = TRUE)
        }
      }
      
      > out
         A  B  C  D  E  F  G  H  I  J  K  L  M  N  O
      A NA  2  1  2 NA  1  1  1  2  1  3  1  1  2  2
      B NA NA  2  1  1  2  1  1  2 NA  3  1  1  2  2
      C NA NA NA NA  3  2  3  1  2 NA  4  2  2  2  2
      D NA NA NA NA NA  2  1  3  2  2  3  1  3  4  2
      E NA NA NA NA NA  2  2  1  1 NA  3  2  2  2  1
      F NA NA NA NA NA NA  2  2  1 NA  4  2  3  4  1
      G NA NA NA NA NA NA NA  2  2 NA  4  1  2  2  1
      H NA NA NA NA NA NA NA NA  3  1  3 NA  2  3  1
      I NA NA NA NA NA NA NA NA NA  1  3 NA  1  2  2
      J NA NA NA NA NA NA NA NA NA NA  1  1  2  2  2
      K NA NA NA NA NA NA NA NA NA NA NA  3  4  5  3
      L NA NA NA NA NA NA NA NA NA NA NA NA  3  3  2
      M NA NA NA NA NA NA NA NA NA NA NA NA NA  5  3
      N NA NA NA NA NA NA NA NA NA NA NA NA NA NA  3
      O NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
      

      【讨论】:

        【解决方案3】:

        这是另一个使用 table 的基本 R 选项:

        pairs <- as.data.frame(do.call(rbind, 
            apply(dat, 1L, function(x) t(combn(na.omit(x), 2L)))))
        
        tab <- table(pairs)
        ut <- tab
        ut[lower.tri(tab)] <- 0L
        lt <- tab
        lt[upper.tri(tab)] <- 0L
        ans <- t(lt) + ut
        ans + t(ans)
        

        输出:

           V1
        V2  A B C D E F
          A 0 2 2 2 3 2
          B 2 0 2 2 1 1
          C 2 2 0 2 1 1
          D 2 2 2 0 1 1
          E 3 1 1 1 0 2
          F 2 1 1 1 2 0
        

        数据:

        dat <- read.table(text="V1 V2 V3 V4 V5 V6 V7
        A B  C  D  NA NA NA
        A E  F  NA NA NA NA
        D A  C  B  'F'  E  NA
        A E  NA NA NA NA NA", header=TRUE, colClasses="character")
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-09-11
          • 1970-01-01
          • 2015-02-21
          • 1970-01-01
          • 2021-11-20
          • 1970-01-01
          • 2022-01-22
          相关资源
          最近更新 更多