From 5df893846675adfb9f6a01abffa5a144e78d3158 Mon Sep 17 00:00:00 2001 From: Claus Hunsen Date: Mon, 17 Dec 2018 10:39:06 +0100 Subject: [PATCH] Further improve construction of edgeless networks When constructing a network in 'construct.network.from.edge.list', several corner cases need to be handled. When there are no edges available, an empty edge list can be created using 'create.empty.edge.list'. This way, reliably, the function 'igraph::graph.data.frame' can be used to construct a network. This further improves the patch 0d7c2226da67f3537f3ff9d013607fe19df8a4c0, which tackles #150. Tests for creating edgeless networks are added to the file 'tests/test-networks.R'. This likely prevents regressions in the future. Additionally, use the function 'create.empty.edge.list' in one further place where possible. Signed-off-by: Claus Hunsen --- tests/test-networks.R | 54 +++++++++++++++++++++++++++++++++++++++++++ util-networks.R | 16 ++++++------- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/tests/test-networks.R b/tests/test-networks.R index 5a9a8489..56942880 100644 --- a/tests/test-networks.R +++ b/tests/test-networks.R @@ -93,3 +93,57 @@ test_that("Merge networks", { }) + +## / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / +## Construction of edgeless networks --------------------------------------- + +test_that("Construction of edgeless networks", { + + ## create data structures and network configuration as a basis + edge.list = data.frame(from = c("D1", "D2"), to = c("D2", "D1")) + edge.list.as.sequence = as.vector(as.matrix(edge.list)) + vertices = data.frame(name = c("D1", "D2")) + vertices.as.sequence = vertices[["name"]] + directed = FALSE # directedness does not matter for this test, but should be consistent + net.conf = NetworkConf$new() + + ## construct edgeless network + net.edgeless = igraph::graph.empty(n = 0, directed = directed) + + igraph::vertices(vertices.as.sequence) + + igraph::edges(NULL, weight = 1) + + ## + ## normal network + ## + + net.constructed = construct.network.from.edge.list(vertices, edge.list, net.conf) + net.expected = igraph::graph.empty(n = 0, directed = directed) + + igraph::vertices(vertices.as.sequence) + + igraph::edges(edge.list.as.sequence, weight = 1) + + ## check equality + expect_true(igraph::identical_graphs(net.constructed, net.expected), label = "normal network construction") + + ## + ## edgeless network: NULL + ## + + net.constructed = construct.network.from.edge.list(vertices, NULL, net.conf) + expect_true(igraph::identical_graphs(net.constructed, net.edgeless), label = "edgeless network: NULL") + + ## + ## edgeless network: create.empty.edge.list() + ## + + net.constructed = construct.network.from.edge.list(vertices, create.empty.edge.list(), net.conf) + expect_true(igraph::identical_graphs(net.constructed, net.edgeless), label = "edgeless network: create.empty.edge.list()") + + ## + ## edgeless network: empty data.frame + ## + + net.constructed = construct.network.from.edge.list(vertices, data.frame(), net.conf) + expect_true(igraph::identical_graphs(net.constructed, net.edgeless), label = "edgeless network: empty data.frame") + +}) + diff --git a/util-networks.R b/util-networks.R index 1584aa3e..8d0eb5d3 100644 --- a/util-networks.R +++ b/util-networks.R @@ -1053,17 +1053,15 @@ construct.network.from.edge.list = function(vertices, edge.list, network.conf, d return(create.empty.network(directed = directed)) } - ## if we have nodes to create, but no edges + ## if we have nodes to create, but no edges, create an empty edge list if (is.null(edge.list) || nrow(edge.list) == 0) { - ## create network with only the vertices - net = igraph::graph.empty(n = 0, directed = directed) + igraph::vertices(t(nodes.processed)) - } - ## if we have nodes and edges - else { - ## construct network from edge list - net = igraph::graph.data.frame(edge.list, directed = directed, vertices = nodes.processed) + edge.list = create.empty.edge.list() } + ## construct network from edge list + net = igraph::graph.data.frame(edge.list, directed = directed, vertices = nodes.processed) + + ## initialize edge weights net = igraph::set.edge.attribute(net, "weight", value = 1) ## transform multiple edges to edge weights @@ -1100,7 +1098,7 @@ merge.network.data = function(vertex.data, edge.data) { edges = plyr::rbind.fill(edge.data.filtered) ## 3) correct empty results if (is.null(edges)) { - edges = data.frame(from = character(0), to = character(0)) + edges = create.empty.edge.list() } logging::logdebug("merge.network.data: finished.")