diff --git a/NAMESPACE b/NAMESPACE index aa5bc8111..1beb1c1d8 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -33,6 +33,7 @@ S3method(as.rlebdm,matrix) S3method(as.rlebdm,network) S3method(as.rlebdm,rlebdm) S3method(c,ergm_model) +S3method(c,network.list) S3method(coef,ergm) S3method(compress,rlebdm) S3method(degreedist,network) diff --git a/R/network.list.R b/R/network.list.R index c5a25f7ad..585614797 100644 --- a/R/network.list.R +++ b/R/network.list.R @@ -100,3 +100,72 @@ summary.network.list <- function (object, stats.print=TRUE, } object } + + + + + +#' @rdname network.list +#' +#' @param check_attr Logical: should the attributes of the combined network +#' lists be checked for consistency. If `TRUE` inconsistencies result in +#' errors. +#' +#' @importFrom purrr map +#' @export +#' +#' @examples +#' # Simulate some more +#' g.sim2 <- simulate(~edges+kstar(2), nsim=3, coef=c(-1.8, 0.03), +#' basis=g.use, control=control.simulate( +#' MCMC.burnin=100000, +#' MCMC.interval=1000)) +#' +#' # Merge the simulations +#' g.simall <- c(g.sim, g.sim2) +#' length(g.simall) # 6 +#' + +c.network.list <- function(..., check_attr = TRUE) { + dots <- list(...) + + # Merge network lists without attributes + rval <- do.call("c", map(dots, unclass)) + + # Check attributes + if (check_attr) { + # Names of attributes to check with `all.equal()` + attr_names <- c("coefficients", "control", "response", + "formula", "constraints", "reference") + for (an in attr_names) { + al <- map(dots, ~ attr(.x, an)) + ok <- all_identical(al, all.equal) + if (!ok) stop("network lists do not have equal values on attribute ", an) + } + + # Check if "stats" have identical columns + l_stats <- map(dots, ~ attr(.x, "stats")) + ok <- all_identical( + map(l_stats, function(x) colnames(x)), + .p = identical + ) + if (!ok) stop("network lists do not have identical columns of ", + sQuote("stats"), " attribute") + } + # Return the list of networks with attributes merged or taken from the + # first object + structure( + rval, + class = "network.list", + coefficients = attr(dots[[1]], "coefficients"), + control = attr(dots[[1]], "control"), + response = attr(dots[[1]], "response"), + stats = structure( + do.call("rbind", map(dots, ~attr(.x, "stats"))), + monitored = do.call("c", map(dots, ~ attr(attr(.x, "stats"), "monitored"))) + ), + formula = attr(dots[[1]], "formula"), + constraints = attr(dots[[1]], "constraints"), + reference = attr(dots[[1]], "reference") + ) +} diff --git a/man/network.list.Rd b/man/network.list.Rd index 60b1444f2..4e584a2db 100644 --- a/man/network.list.Rd +++ b/man/network.list.Rd @@ -5,6 +5,7 @@ \alias{network.list.list} \alias{print.network.list} \alias{summary.network.list} +\alias{c.network.list} \title{A convenience container for a list of \code{\link[network:network]{network}} objects, output by \code{\link[=simulate.ergm]{simulate.ergm()}} among others.} \usage{ @@ -19,6 +20,8 @@ network.list(object, ...) net.summary = FALSE, ... ) + +\method{c}{network.list}(..., check_attr = TRUE) } \arguments{ \item{object, x}{a \code{list} of networks or a \code{network.list} object.} @@ -32,6 +35,10 @@ lower-level functions.} \item{net.print}{Logical: If TRUE, print network overviews.} \item{net.summary}{Logical: If TRUE, print network summaries.} + +\item{check_attr}{Logical: should the attributes of the combined network +lists be checked for consistency. If \code{TRUE} inconsistencies result in +errors.} } \description{ A convenience container for a list of \code{\link[network:network]{network}} objects, output @@ -67,6 +74,16 @@ g.sim <- simulate(~edges+kstar(2), nsim=3, coef=c(-1.8, 0.03), print(g.sim) summary(g.sim) +# Simulate some more +g.sim2 <- simulate(~edges+kstar(2), nsim=3, coef=c(-1.8, 0.03), + basis=g.use, control=control.simulate( + MCMC.burnin=100000, + MCMC.interval=1000)) + +# Merge the simulations +g.simall <- c(g.sim, g.sim2) +length(g.simall) # 6 + } \seealso{ \code{\link[=simulate.ergm]{simulate.ergm()}} diff --git a/tests/testthat/test-network.list.R b/tests/testthat/test-network.list.R new file mode 100644 index 000000000..a9b9133f4 --- /dev/null +++ b/tests/testthat/test-network.list.R @@ -0,0 +1,28 @@ +suppressMessages({ + net0 <- network.initialize(36) + net0 %v% "x" <- rep(1:2, length = network.size(net0)) + k <- c(-2, -3, -3, -2) + s1 <- simulate(net0 ~ mm("x", levels2=TRUE), nsim=10, coef = k) + s2 <- simulate(net0 ~ mm("x", levels2=TRUE), nsim=10, coef = k * 0.01) +}) + +test_that("there is no error if attributes match", { + expect_silent( + c(s1, s1) + ) + expect_silent( + c(s1, s1) + ) +}) + +test_that("there is an error if attributes don't match", { + expect_error( + c(s1, s2) + ) +}) + +test_that("there is no error if attributes are to be ignored", { + expect_silent( + c(s1, s2, check_attr = FALSE) + ) +})