Как преобразовать двудольную сеть и использовать атрибуты узла с одного уровня в качестве веса ребер на втором уровне в igraph (R) - PullRequest
0 голосов
/ 19 февраля 2020

Сейчас я пытаюсь перевести двудольный двухрежимный граф в его одномодовое представление. Проблема в том, что я хочу сохранить атрибуты узлов из двухрежимного графа в одномодовых представлениях. Например, фрейм данных задается следующим образом:

Person EventLocation DurationEvent Peter Bar 90 Jack Bar 90 Franz Train 20 Franz Bar 90 Laurie Train 20 Jack Train 20 ...

Теперь я хочу получить сеть людей с помощью функции igraph bipartite_projection () в столбцах Person и EventLocation, но не вижу способов, как Presafe дополнительные атрибуты узла (длительность), которые могут быть перенесены в граничные веса между людьми, например, Питер-Джек с весом 90 или Франц-Лаур ie с весом 20.

Редактировать: я добавил последнюю строку чтобы быть более точным. Край "Джек-Франц" теперь будет соответствовать 90 + 20 = 110. Но в основном моя проблема просто связана с тем, как реализовать bipartite_projection, которое переносит атрибут узла двудольной igraph-сети в атрибут ребра соответствия в одномодовом режиме. igraph-сети.

Редактировать 2: Я только что добавил еще один пример. Сначала я создаю сеть между людьми, затем я хочу добавить информацию о бюджете к границам людей, подразумевая, сколько бюджета проекта привлекли оба (сумма бюджетов только из разных уникальных проектов в качестве весов). Затем я хотел сделать некоторые дальнейшие взвешенные вычисления центральности:

person_id <- c("X","Y","Z","Q","W","E","R","X","Y")
project <- c("a","b","c","a","a","b","c","b","a")
budget <- c(100,200,300,100,100,200,300,200,100)
employ.data <- data.frame(person_id, project, budget)
View(employ.data)
sna.complete.list <- employ.data
sna.list.complete.igraph.calc <- graph.data.frame(sna.complete.list)
V(sna.list.complete.igraph.calc)$type <- V(sna.list.complete.igraph.calc)$name%in%sna.complete.list$person_id
sna.list.complete.igraph.calc.one <- try(bipartite.projection(sna.list.complete.igraph.calc, type=V(sna.list.complete.igraph.calc)$type))
sna.statistics.persons <- sna.list.complete.igraph.calc.one[[2]]
plot.igraph(sna.statistics.persons)

EDIT3: я пытаюсь переформулировать мою проблему:

Общая цель: получить взвешенный график (граничные значения между узлами, взвешенными с некоторыми значения)

Схема / Данные:

  1. Данные о людях, участвующих в различных проектах, которые отличаются по размеру бюджета

  2. Преобразовать двудольный график подключения (People-Project) к графику one-mode-People-People

  3. Используйте размеры бюджета в качестве весов для границ между людьми.

НО для двух человек это значение должно учитывать только сумму участия в уникальных проектах. Таким образом, если A и B связаны только проектом x с размером бюджета 100, это должно привести к граничному весу 100. Если они также участвуют в другом проекте со значением 20, результат должен быть 120 et c.

Я пытался передать эту информацию во время использования bipartite.projection, но не смог или не смог реализовать эту информацию впоследствии.

1 Ответ

1 голос
/ 20 февраля 2020

bipartite_projection() может собирать только структурные веса ребер , то есть Питер и Джек оба связаны с Train и Bar. Обрабатывать атрибуты edge сложнее.

Если вы хотите сохранить только атрибуты node , как вы пишете выше, bipartite_projection() уже сделает это за вас , Просто перепроектируйте и найдите, что ваши атрибуты сохранены следующим образом:

V(unipartite_graph)$your_attributee

Если вам нужно сохранить атрибуты edge при перепроецировании, однако, есть несколько вопросов, которые нужно задать ранее.

  • Как следует обрабатывать несколько путей, если у Франца-Трэйна-Джека также есть Franz-Bar_Jack?
  • Какую роль играет направленность в расчете

Несколько лет назад мне нужно было то же самое, и я решил это, написав собственную расширенную функцию повторного проецирования. Возможно, это не самый короткий путь, но он вычисляет суммы заданного реберного атрибута по кратчайшему пути между каждой парой unipartite-vertex в двудольного графа и возвращает граф с one атрибут ребра сохранен (и суммирован).

Reprojection with summarised edge attributes

Обратите внимание, что функция не вычисляет односторонний Лаур ie -Петр. Вы можете манипулировать функцией по своему вкусу.

Воспроизводит данные вашего примера и применяет мою функцию

# Reproduce your data
df <- data.frame(Person = c("Peter","Jack","Franz","Franz","Laurie","Jack"),
                 EventLocation = c("Bar","Bar","Train","Bar","Train","Train"),
                 DurationEvent = c(90,90,20,90,20,20), stringsAsFactors = F)


## Make bipartite graph from example data
g <- graph_from_data_frame(df, directed=FALSE)
# Set vertex type using bipartite.mapping() (OBS type should be boolean for bipartite_projection())
V(g)$type <- bipartite.mapping(g)$type


## Plot Bipartite graph
E(g)$label <- E(g)$DurationEvent
V(g)$color <- ifelse(V(g)$type, "red", "yellow")
V(g)$size <- ifelse(V(g)$type, 40, 20)
plot(g, edge.label.color="gray", vertex.label.color="black")

# Function to reproject a bipartite graph to unipartite projection while
# calculating an attribute-value sum between reprojected vertecies.
unipartite_projection_attr <- function(graph_bi, attribute, projection=FALSE){

  ## Make initial unipartite projection
  graph_uni <- bipartite_projection(graph_bi, which=FALSE)

  ## List paths in bipartite-graph along which to summarise selected attribute
  el <- as_edgelist(graph_uni)
  el <- matrix(sapply(el, function(x) as.numeric(which(x == V(graph_bi)$name))), ncol=2)

  ## Function to summarise given atribute-value
  summarise_graph_attribute_along_path <- function(source, target, attribute){
    attr_value <- edge_attr(g, attribute)
    path <- get.shortest.paths(g, source, target, output="epath")$epath[[1]]
    sum(E(g)$DurationEvent[path])
  }

  attr_uni <- mapply(summarise_graph_attribute_along_path, el[,1], el[,2], attribute)
  graph_uni <- set_edge_attr(graph_uni, attribute, value=attr_uni)

  (graph_uni)
}

# Use function to make unipartite projection
gg <- unipartite_projection_attr(g, "DurationEvent", FALSE)

# Visualise
V(gg)$color <- "yellow"
E(gg)$label <- E(gg)$DurationEvent
plot(gg, edge.label.color="gray", vertex.label.color="black")

Удачи

...