首页 > 解决方案 > 创建类似距离矩阵的东西

问题描述

我有一个 3 列矩阵,其中包含 ID 和它们之间的分数。

> df1
           ID_1       ID_2    Score
  1: 1000020760 1000534822 1.70e-01
  2: 1000020760 1000535109 1.10e+00
  3: 1000020760 1000532510 3.20e+00
  4: 1000020760 1000535228 3.70e+00
  5: 1000035849 1000532512 2.49e-60
 ---                               
600: 1000773219 1000483302 2.40e+00
601: 1000773219 1000734829 8.50e+00
602: 1000773219 1000535109 1.00e+01
603: 1000773304 1000730133 5.80e+00
604: 1000773304 1000752994 9.20e+00

第一列中的每个值都有第二列中的几个对应值(包括缺少值)。第三列的值不会超过前两列。例如:

> df1[4,]
         ID_1       ID_2 Score
1: 1000020760 1000535228   3.7

> df1[294,]
         ID_1       ID_2 Score
1: 1000535228 1000020760   3.9

相同的身份证,但站在不同的地方,有不同的分数。

我想创建一个矩阵 m * m (m 是 和 中唯一 ID 的最大数量df1$ID_1df1$ID_2,哪些元素是输入表第三列中的相应值。输出矩阵的行和列必须由 ID 组成,并且在交点处 - 来自Score输入矩阵列的对应值。主对角线上的值必须等于 0,缺失值必须等于NA

例如,如果我有这样的输入

> tmp1
         ID_1       ID_2 Score
1: 1000020760 1000534822  0.17
2: 1000020760 1000535109  1.10
3: 1000020760 1000532510  3.20
4: 1000020760 1000535228  3.70
5: 1000535228 1000483302  2.50
6: 1000535228 1000020760  3.90
7: 1000535228 1000414853  5.10
8: 1000534822 1000020760  0.06

我想看到这样的输出

> tmp_mat
           1000534822 1000535109 1000532510 1000535228 1000483302 1000020760 1000414853
1000534822       0.00         NA         NA         NA         NA       0.06         NA
1000535109         NA        0.0         NA         NA         NA         NA         NA
1000532510         NA         NA        0.0         NA         NA         NA         NA
1000535228         NA         NA         NA        0.0        2.5       3.90        5.1
1000483302         NA         NA         NA         NA        0.0         NA         NA
1000020760       0.17        1.1        3.2        3.7         NA       0.00         NA
1000414853         NA         NA         NA         NA         NA         NA        0.0

标签: r

解决方案


包含 和 的唯一值的向量ID_1ID_2扩展以获得所有组合。Scores然后在可用的地方包括在内,并对角元素归零。最后可以将结果重新格式化为一个wide tibble。使用该tidyverse库,代码将是

library(tidyverse)

ID_table <- unique(x = c(df1$ID_1, df1$ID_2)) %>% sort() %>% expand_grid(ID_1 = ., ID_2 = .) %>%
            left_join(df1, by = c("ID_1", "ID_2")) %>% mutate(Score = ifelse(ID_1 == ID_2, 0, Score)) %>%
            pivot_wider(names_from = ID_2, values_from = Score)

结果

# A tibble: 7 x 8
        ID_1 `1000020760` `1000414853` `1000483302` `1000532510` `1000534822` `1000535109` `1000535228`
       <int>        <dbl>        <dbl>        <dbl>        <dbl>        <dbl>        <dbl>        <dbl>
1 1000020760         0            NA           NA            3.2         0.17          1.1          3.7
2 1000414853        NA             0           NA           NA          NA            NA           NA  
3 1000483302        NA            NA            0           NA          NA            NA           NA  
4 1000532510        NA            NA           NA            0          NA            NA           NA  
5 1000534822         0.06         NA           NA           NA           0            NA           NA  
6 1000535109        NA            NA           NA           NA          NA             0           NA  
7 1000535228         3.9           5.1          2.5         NA          NA            NA            0 

推荐阅读