【问题标题】:Create a matrix of pairwise comparisons between columns创建列之间的成对比较矩阵
【发布时间】:2021-04-15 18:34:35
【问题描述】:

我想创建一个矩阵,显示每个成对列比较的行差异数。这就是我要开始的:

     Ind1 Ind2 Ind3
Att1    A    A    B
Att2    A    C    C
Att3    B    B    D

这就是我想要的结果:

      Ind1  Ind2  Ind3
Ind1            
Ind2    1       
Ind3    3     2 

如何在 Python 或 R 中做到这一点?

【问题讨论】:

  • 将来,一次选择一个语言标签可能会更好。否则你会得到两种语言的答案,而没有人告诉你哪个是哪个。

标签: python r pandas dataframe


【解决方案1】:

尝试adist,如下所示

> adist(sapply(df, toString))
     Ind1 Ind2 Ind3
Ind1    0    1    3
Ind2    1    0    2
Ind3    3    2    0

【讨论】:

    【解决方案2】:

    你可以试试下面的

    df <- read.table(header = TRUE, text = "     Ind1 Ind2 Ind3
    Att1    A    A    B
    Att2    A    C    C
    Att3    B    B    D")
    
    v <- apply(combn(1:ncol(df), 2), 2, function(k) sum(df[, k[1]] != df[, k[2]]))
    M <- matrix(0, nrow = ncol(df), ncol = ncol(df))
    M[lower.tri(M)] <- v
    M
    
         [,1] [,2] [,3]
    [1,]    0    0    0
    [2,]    1    0    0
    [3,]    3    2    0
    

    【讨论】:

    • 请注意combn(1:ncol(df),2)==combn(ncol(df),2)。没想到lower.tri 把戏:不错!
    • 哦,是的@Waldi。 OP你可以同时使用这两个版本。谢谢提醒!
    【解决方案3】:

    用途:

    arr = df.values.T
    arr = np.sum(arr[:, None] != arr, axis = -1)
    mask = np.triu(np.ones(arr.shape)) == 0
    arr = np.where(mask, arr, np.nan)
    
    >>> pd.DataFrame(data = arr, index = df.columns, columns = df.columns)
          Ind1  Ind2  Ind3
    Ind1   NaN   NaN   NaN
    Ind2   1.0   NaN   NaN
    Ind3   3.0   2.0   NaN
    

    【讨论】:

      【解决方案4】:

      另一种基本 R 方法:

      x <- combn(df, 2, function(x)sum(do.call("!=", x)))
      
      attributes(x) <- list(Labels = names(df), Size = ncol(df), class = "dist")
      
      x
           Ind1 Ind2
      Ind2    1     
      Ind3    3    2
      

      如果你愿意,你可以这样做:

      as.matrix(x)
           Ind1 Ind2 Ind3
      Ind1    0    1    3
      Ind2    1    0    2
      Ind3    3    2    0
      

      【讨论】:

      • 对于 Python,你可以这样做:pd.DataFrame((df.values.T != df.values.T[:, None]).sum(2), columns=df.columns, index=df.columns)
      【解决方案5】:

      1) sapply 对指定的函数执行双重sapply。我们可以选择在此使用 as.dist 并在稍后显示的其他替代方案上类似地使用,但不会对每个都重复。

      nc <- ncol(m)
      res <- sapply(1:nc, function(i) sapply(1:nc, function(j) sum(m[, i] != m[, j])))
      
      res
      ##      [,1] [,2] [,3]
      ## [1,]    0    1    3
      ## [2,]    1    0    2
      ## [3,]    3    2    0
      

      as.dist(res)
      ##   1 2
      ## 2 1  
      ## 3 3 2
      

      2) 列表理解 使用 eList 包,我们可以像这样生成它:

      library(eList)
      
      nc <- ncol(m)
      Mat(for(i in 1:nc) for(j in 1:nc) sum(m[, i] != m[, j]))
      ##      [,1] [,2] [,3]
      ## [1,]    0    1    3
      ## [2,]    1    0    2
      ## [3,]    3    2    0
      

      3) 外层 我们可以像这样使用outer

      f <- function(i, j) sum(m[, i] != m[, j])
      outer(1:nc, 1:nc, Vectorize(f))
      ##      [,1] [,2] [,3]
      ## [1,]    0    1    3
      ## [2,]    1    0    2
      ## [3,]    3    2    0
      

      注意

      m <- structure(c("A", "A", "B", "A", "C", "B", "B", "C", "D"), .Dim = c(3L, 
      3L), .Dimnames = list(c("Att1", "Att2", "Att3"), c("Ind1", "Ind2", 
      "Ind3")))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-24
        • 2014-04-22
        • 2012-09-22
        • 2012-03-08
        • 1970-01-01
        • 2019-10-08
        相关资源
        最近更新 更多