Создание сгруппированных списков ребер

#r #igraph

#r #igraph

Вопрос:

У меня есть список людей, и я хочу изучить характеристики их сетей совместной работы. Однако я хочу использовать все ребра их сетей, а не только ребра, которые напрямую связаны с ними. Например, предположим, что я смотрю на сеть Боба. Для проекта 1 Боб, Билл и Джейн работали вместе.

Если бы я заботился только о ребрах, связанных с Бобом, тогда мой список ребер был бы: Боб-Билл, Боб-Джейн. В сети будет 0 треугольников. Однако, если бы я посмотрел на все ребра для сети Боба, список ребер выглядел бы так: Боб-Билл, Боб-Джейн, Билл-Джейн. Сеть будет иметь 1 треугольник.

Единственный способ сделать это, который я могу придумать, — создать «сгруппированный» список ребер. Я просто не уверен, как с этим справиться.

Мои данные ребер выглядят следующим образом:

 collab <- data.frame(vertex1 = c("Bob","Bill","Bob","Jane","Bill","Jane","Bob","Jane","Bob","Bill","Bob"
                                  ,"Jane","Bill","Jane","Bob","Jane","Jane","Jill","Jane","Susan","Susan"),
                      edgeID = c(1,1,1,1,1,1,2,2,1,1,1,1,1,1,2,2,3,3,3,3,3),
                      vertex2 = c("Bill","Bob","Jane","Bob","Jane","Jill","Jane","Bob","Bill","Bob"
                                  ,"Jane","Bob","Jane","Bill","Jane","Bob","Jill","Jane","Susan","Jane","Jill"))
 
    vertex1 edgeID vertex2
1      Bob      1    Bill
2     Bill      1     Bob
3      Bob      1    Jane
4     Jane      1     Bob
5     Bill      1    Jane
6     Jane      1    Jill
7      Bob      2    Jane
8     Jane      2     Bob
9     Jane      3    Jill
10    Jill      3    Jane
11    Jane      3   Susan
12   Susan      3    Jane
13   Susan      3    Jill
 

У меня есть другой вектор, который содержит имена моих целевых пользователей:

 targets <- data.frame(name=c("Bob","Jane"))
 

Что я хотел бы сделать, так это сгруппировать соответствующие ребра под соответствующими целями, чтобы результат был примерно таким:

    group vertex1 edgeID vertex2
1    Bob     Bob      1    Bill
2    Bob    Bill      1     Bob
3    Bob     Bob      1    Jane
4    Bob    Jane      1     Bob
5    Bob    Bill      1    Jane
6    Bob    Jane      1    Jill
7    Bob     Bob      2    Jane
8    Bob    Jane      2     Bob
9   Jane     Bob      1    Bill
10  Jane    Bill      1     Bob
11  Jane     Bob      1    Jane
12  Jane    Jane      1     Bob
13  Jane    Bill      1    Jane
14  Jane    Jane      1    Bill
15  Jane     Bob      2    Jane
16  Jane    Jane      2     Bob
17  Jane    Jane      3    Jill
18  Jane    Jill      3    Jane
19  Jane    Jane      3   Susan
20  Jane   Susan      3    Jane
21  Jane   Susan      3    Jill
 

Я полагаю, что если я смогу добраться сюда, я смогу создать цикл for, который перебирает каждую цель, создает график с помощью iGraph и вычисляет сетевые показатели для Боба и Джейн без особых проблем. Правильно ли я поступаю или у iGraph есть лучший способ сделать это?

Ответ №1:

Здесь может быть один из вариантов

 g <- graph_from_data_frame(collab[c(1, 3, 2)], directed = FALSE)
do.call(
  rbind,
  c(
    make.row.names = FALSE,
    lapply(
      targets$name,
      function(nm) {
        z <- c(nm, V(g)$name[distances(g, nm) == 1])
        cbind(group = nm, unique(subset(collab, vertex1 %in% z amp; vertex2 %in% z)))
      }
    )
  )
)
 

что дает

    group vertex1 edgeID vertex2
1    Bob     Bob      1    Bill
2    Bob    Bill      1     Bob
3    Bob     Bob      1    Jane
4    Bob    Jane      1     Bob
5    Bob    Bill      1    Jane
6    Bob     Bob      2    Jane
7    Bob    Jane      2     Bob
8    Bob    Jane      1    Bill
9   Jane     Bob      1    Bill
10  Jane    Bill      1     Bob
11  Jane     Bob      1    Jane
12  Jane    Jane      1     Bob
13  Jane    Bill      1    Jane
14  Jane    Jane      1    Jill
15  Jane     Bob      2    Jane
16  Jane    Jane      2     Bob
17  Jane    Jane      1    Bill
18  Jane    Jane      3    Jill
19  Jane    Jill      3    Jane
20  Jane    Jane      3   Susan
21  Jane   Susan      3    Jane
22  Jane   Susan      3    Jill
 

Комментарии:

1. Это отлично работает с образцами данных, которые я предоставил, но когда я пробую это на своих реальных данных, я получаю следующую ошибку: «Ошибка в расстояниях (g, nm): на итераторах.c: 759: невозможно создать итератор, неверный идентификатор вершины, неверный идентификатор вершины» Есть идеи, что это можетбыть?

2. Понял это. В моих фактических данных столбец targets$name является числовым. Передача числа в функцию distances() приводит к тому, что она обрабатывает число как индекс, что приводит к недопустимому идентификатору вершины. Вместо этого я передаю «как.character(targets$name)», чтобы заставить его учитывать имя вершины, а не рассматривать его как номер индекса.