【问题标题】:Convert 2 columns to adjacency matrix将 2 列转换为邻接矩阵
【发布时间】:2019-08-05 20:03:45
【问题描述】:

我对 R 和这个论坛还很陌生,请帮助我。

我有两列数据

  • 具有类 ID 的第一列
  • 第二列有学生的 ID

我想将其转换为边缘列表,其中

  • 具有类 ID 的第一列
  • 第 2 列的类 id
  • 第 3 列包含 2 个班级共享的学生人数的值

我还想创建一个邻接矩阵(行和列是类)

我在这个论坛上搜索并尝试使用full_join,但是没有共享任何普通学生的类被排除在外,而不是保留它们并将值设置为0。

任何人都可以帮助我找到包含 2 个类的所有成对的边缘列表的代码吗?并帮助我处理所有类的邻接矩阵(不删除孤立的类)?

非常感谢。

data <- full_join(mydata, mydata, c('studentid' = 'studentid')) %>% 
select(-studentid) %>% 
filter(classid.x != classid.y) %>% 
group_by(classid.x, classid.y) %>% summarise(weight = n()) 
mydata <- read.table(header=TRUE, text="
  classid   studentid
0036110 03576311
0036110 08195612
0036110 20302811
0036110 29681210
0036110 03484975
0036110 03484815
0036110 04583310
0036110 06919310
0036110 03576211
0088630 10249511
0088630 00662458
0088630 00419766
0088630 10248511
0088630 10247911
0088630 10250611
0088630 00426947
0088630 00105669
0088630 10100910
0088630 00781739
0095710 02255772
0095710 02255742
0095710 02255782
0095710 02255682
0095710 02255752
0095710 04625310
0095710 02255722
0095710 02255692
0108410 01587447
0108410 10248511
0108410 00730873
0108410 01587497
0108410 00051469
0108410 01587397
0108410 01587587
0108410 00310447
0108410 01587457
0154710 20302811
0154710 01068245
0154710 00409605
0154710 02309283
0154710 00635705
0154710 03721112
0154710 02434835
0154710 00409755
0154710 00657098
0154710 02309263
0176510 03679107
0176510 00303516
0176510 00435928
0176510 00188526
0176510 00450059
0176510 00430397
0176510 01595488
0176510 10248511
0176510 07911110
0176510 00417916
0176510 00341139
0176510 00327468
0176510 00418006
0191U10 04778988
0191U10 04780648
0191U10 04780798
0191U10 04844509
0191U10 04780938
0195750 00305336
0195750 40866711
0195750 00625644
0206R10 04605910
0206R10 00010502
0206R10 00421056
0206R10 00421066
0206R10 00420986
0206R10 00421006
0206R10 00220119
0206R10 00420816
0206R10 00440028
0206R10 00416026
0206R10 00043863
0206R10 00625754
0206R10 00403354
0206R10 00431227
0206R10 00403314
0206R10 00412295
0206R10 04604810
0206R10 21078752
0206R10 00420926
0206R10 04608910
")

【问题讨论】:

  • 请附上您的data 的样本。
  • @ArtemSokolov,感谢您的留言,请再次查看我帖子中的数据。

标签: r adjacency-matrix


【解决方案1】:

full_join 正确地保留了所有的类 id,但是你通过filter(classid.x != classid.y) 丢弃了一些。这实际上是邻接矩阵的对角线;如果您想要对角线上的零,更好的方法是明确设置它们。然后可以通过tidyr::spread 填充非对角线条目:

X <- full_join(mydata, mydata, c('studentid' = 'studentid')) %>%
  group_by(classid.x, classid.y) %>% summarise(weight = n()) %>%
  mutate(weight = replace(weight, classid.x==classid.y, 0)) %>%
  ungroup() %>% tidyr::spread(classid.y, weight, fill=0)
# # A tibble: 9 x 10
#   classid.x `0036110` `0088630` `0095710` `0108410` `0154710` `0176510`
#   <fct>         <dbl>     <dbl>     <dbl>     <dbl>     <dbl>     <dbl>
# 1 0036110           0         0         0         0         1         0
# 2 0088630           0         0         0         1         0         1
# 3 0095710           0         0         0         0         0         0
# 4 0108410           0         1         0         0         0         1
# 5 0154710           1         0         0         0         0         0
# 6 0176510           0         1         0         1         0         0
# 7 0191U10           0         0         0         0         0         0
# 8 0195750           0         0         0         0         0         0
# 9 0206R10           0         0         0         0         0         0
# # … with 3 more variables: `0191U10` <dbl>, `0195750` <dbl>, `0206R10` <dbl>

从这里,你可以把它变成一个合适的矩阵

X %>% as.data.frame %>% tibble::column_to_rownames( "classid.x" ) %>% as.matrix

或将其转换回长格式的数据帧

X %>% tidyr::gather( classid.y, weight, -classid.x )

【讨论】:

  • 非常感谢您的帮助。但一开始,我的数据有 500 个独特的班级,在我做的这一步之后,不共享任何学生的班级被删除(例如,只保持权重 >=1,只剩下 380 个)。即使我使用您的代码,它们也只能在 380 类上运行。你能帮我修复我的代码以保留所有课程(即使他们不共享任何学生)?
  • @KenYang:看起来问题是filter()。请查看我的更新答案。
  • 现在一切正常!非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-05
相关资源
最近更新 更多