【问题标题】:How to take only one connection from a matrix如何从矩阵中仅获取一个连接
【发布时间】:2021-06-05 00:43:41
【问题描述】:

我有一个矩阵,如下所示

       ID_1 ID_2 ID_3 ID_4 ID_8 ID_5 ID_7 ID_100
ID_1      0    1    1    1  Inf    2    2    Inf
ID_2      1    0    2    1  Inf    1    2    Inf
ID_3      1    2    0    2  Inf    3    1    Inf
ID_4      1    1    2    0  Inf    2    1    Inf
ID_8    Inf  Inf  Inf  Inf    0  Inf  Inf      1
ID_5      2    1    3    2  Inf    0    3    Inf
ID_7      2    2    1    1  Inf    3    0    Inf
ID_100  Inf  Inf  Inf  Inf    1  Inf  Inf      0

我使用了as.data.frame.tablefilter,因为我只想要那些具有 3 的值。输出看起来像

  nodeA nodeB score
1  ID_5  ID_3     3
2  ID_3  ID_5     3
3  ID_7  ID_5     3
4  ID_5  ID_7     3

我写的代码

mat_pi_lon <- as.data.frame.table(mat, responseName = "score") %>%
  filter(score ==3) %>%
  rename(nodeA = Var1, nodeB = Var2)

但是,我的实际预期输出如下所示。因为,ID_3 ID_5 3 and ID_5 ID_3 3 是相同的(就概念而言)。所以,我只想要ID_3 ID_5 3 而不是ID_5 ID_3 3

  nodeA nodeB score
1  ID_3  ID_5     3
2  ID_5  ID_7     3

可以减少输出吗?

可重现的数据

structure(c(0, 1, 1, 1, Inf, 2, 2, Inf, 1, 0, 2, 1, Inf, 1, 2, 
Inf, 1, 2, 0, 2, Inf, 3, 1, Inf, 1, 1, 2, 0, Inf, 2, 1, Inf, 
Inf, Inf, Inf, Inf, 0, Inf, Inf, 1, 2, 1, 3, 2, Inf, 0, 3, Inf, 
2, 2, 1, 1, Inf, 3, 0, Inf, Inf, Inf, Inf, Inf, 1, Inf, Inf, 
0), .Dim = c(8L, 8L), .Dimnames = list(c("ID_1", "ID_2", "ID_3", 
"ID_4", "ID_8", "ID_5", "ID_7", "ID_100"), c("ID_1", "ID_2", 
"ID_3", "ID_4", "ID_8", "ID_5", "ID_7", "ID_100")))

【问题讨论】:

    标签: r matrix dplyr


    【解决方案1】:

    您可以将字符串与&lt;= 进行比较,但不能与因子进行比较。因此,在过滤所有 Var1 &gt; Var2 之前,将 Var1Var2 强制转换为字符。

    library(dplyr)
    
    mat %>% as.data.frame.table(responseName = "score") %>%
      mutate(Var1 = as.character(Var1),
             Var2 = as.character(Var2)) %>%
      filter(score == 3 & Var1 <= Var2) %>%
      rename(nodeA = Var1, nodeB = Var2)
    #  nodeA nodeB score
    #1  ID_3  ID_5     3
    #2  ID_5  ID_7     3
    

    【讨论】:

      【解决方案2】:

      我们可以使用pmin/pmax按行重新排列元素,使用duplicated删除重复元素

      library(dplyr)
      mat_pi_lon %>% 
         filter(!duplicated(cbind(pmin(as.character(nodeA), 
                  as.character(nodeB)),
              pmax(as.character(nodeA), as.character(nodeB)))))
      #  nodeA nodeB score
      #1  ID_5  ID_3     3
      #2  ID_7  ID_5     3
      

      或者在单行中使用base R

      subset(mat_pi_lon, !duplicated(t(apply(mat_pi_lon, 1, sort))))
      #   nodeA nodeB score
      #1  ID_5  ID_3     3
      #3  ID_7  ID_5     3
      

      【讨论】:

        【解决方案3】:

        您可以先replaceupper.triNA,从而节省一些步骤。

        library(dplyr)
        mat %>%
          replace(., upper.tri(.), NA) %>%
          as.data.frame.table(responseName="score") %>%
          filter(score %in% 3)
        #   Var1 Var2 score
        # 1 ID_5 ID_3     3
        # 2 ID_7 ID_5     3
        

        使用基础 R:

        mat[upper.tri(mat)] <- NA
        d <- as.data.frame.table(mat, responseName="score")
        d[d$score %in% 3, ]
        #    Var1 Var2 score
        # 22 ID_5 ID_3     3
        # 47 ID_7 ID_5     3
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-13
          • 2021-01-17
          • 2023-02-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多