R - построить матрицу смежности на основе другой матрицы смежности

У меня есть данные, которые похожи на эти две матрицы смежности:

data1999 <- data.frame(node1=c("A", "A", "B", "D", "B", "C", "D"),
                   node2=c("A", "A", "D", "B", "B", "C", "D"),
                   link=c(1, 1, 1, 1, 1, 1, 1),
                   stringsAsFactors = FALSE)

adj.m1999 <- reshape2::acast(data1999, node1 ~ node2)

> adj.m1999
  A B C D
A 2 0 0 0
B 0 1 0 1
C 0 0 1 0
D 0 1 0 1


data2000 <- data.frame(node1=c("A", "A", "B", "C", "D", "C", "D"),
                   node2=c("A", "A", "B", "C", "D", "D", "C"),
                   link=c(1, 1, 1, 1, 1, 1, 1),
                   stringsAsFactors = FALSE)

adj.m2000 <- reshape2::acast(data2000, node1 ~ node2)

> adj.m2000
  A B C D
A 2 0 0 0
B 0 1 0 0
C 0 0 1 1
D 0 0 1 1

Обратите внимание, что в 1999 году узлы D и B имеют ссылку.

Обратите внимание, что в 2000 году узлы D и C имеют ссылку.

Основываясь на этой информации, я хочу построить новую матрицу смежности (со всеми узлами моих данных 2000 года), в которой BD и DB имеют значение 1, а остальные - ноль:

> result
  A B C D
A 0 0 0 0
B 0 0 1 0
C 0 1 0 0
D 0 0 0 0  

В моих реальных данных данные 1999 года могут иметь дополнительные узлы, которые не возвращаются в 2000 году и наоборот.

Есть идеи?

1 ответ

Решение

В теории графов произведение двух матриц смежности m1 и m2 дает в позиции (i,j) количество способов пройти от i до j, пройдя сначала через m1, а затем через m2. Это связано с тем, что вы хотите, но не совсем так, как если бы мы adj.m1999 %*% adj.m2000, мы получаем:

  A B C D
A 4 0 0 0
B 0 1 1 1
C 0 0 1 1
D 0 1 1 1

Так, например, вы можете перейти от C к D одним способом, и это будет C -> C, за которым следует C -> D. В вашем примере вы не учитываете ссылки (или ребра), которые находятся на Диагональ, а также ваш график не направлены, поэтому, если я правильно понимаю, что вы хотите, вы могли бы сделать:

## First make sure that you have in adj.m1999 only nodes that appear in adj.m2000:
adj.m1999 = adj.m1999[row.names(adj.m1999) %in% row.names(adj.m2000),colnames(adj.m1999) %in% colnames(adj.m2000)]
## Then turn both diagonals into zeros:
diag(adj.m1999) = 0
diag(adj.m2000) = 0
## Finally, get the sum of the two products
res = adj.m1999 %*% adj.m2000 + adj.m2000 %*% adj.m1999
  A B C D
A 0 0 0 0
B 0 0 1 0
C 0 1 0 0
D 0 0 0 0
Другие вопросы по тегам