From 1f4401ed73356cbf89c2f35fd35d6a981f4caea0 Mon Sep 17 00:00:00 2001 From: "Pavel N. Krivitsky" Date: Tue, 2 Jul 2024 16:46:12 +0100 Subject: [PATCH] In ergm_edgecov_args(), the helper for edgecov() and dyadcov() terms, fixed handling of network input and implemented a dimension check for the covariate matrix; documentation cleaned up as well. fixes statnet/ergm#568 --- DESCRIPTION | 4 ++-- R/InitErgmTerm.R | 10 +++++++++- man-roxygen/ergmTerm-x-attrname.R | 23 ++++++++++++++++------- man/dyadcov-ergmTerm-5fba5404.Rd | 23 ++++++++++++++++------- man/edgecov-ergmTerm-1fb5ef19.Rd | 23 ++++++++++++++++------- tests/testthat/test-term-flexible.R | 10 ++++++++++ 6 files changed, 69 insertions(+), 24 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index f3716cf8b..787140e94 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: ergm -Version: 4.7-7368 -Date: 2024-06-11 +Version: 4.7-7374 +Date: 2024-07-02 Title: Fit, Simulate and Diagnose Exponential-Family Models for Networks Authors@R: c( person(c("Mark", "S."), "Handcock", role=c("aut"), email="handcock@stat.ucla.edu"), diff --git a/R/InitErgmTerm.R b/R/InitErgmTerm.R index c5f0ea62f..61668b0c3 100644 --- a/R/InitErgmTerm.R +++ b/R/InitErgmTerm.R @@ -202,7 +202,7 @@ ergm_edgecov_args <- function(name, nw, a){ xm <- as.matrix(a$x, matrix.type="adjacency", a$attrname) }else if(is.character(a$x)){ xm <- get.network.attribute(nw, a$x) - if(is.null(xm) || !is.matrix(xm)) ergm_Init_abort("There is no network attribute named ", sQuote(a$x), " or it is not a matrix.") + if(is.null(xm) || !(is.matrix(xm) || is.network(xm))) ergm_Init_abort("There is no network attribute named ", sQuote(a$x), " or it is not a matrix or a network.") if(is.network(xm)){ if(!is.null(a$attrname) && !a$attrname %in% list.edge.attributes(xm)) ergm_Init_abort("Network at attribute named ", sQuote(a$x), " does not have an edge attribute ", sQuote(a$attrname), ".") xm <- as.matrix(xm, matrix.type="adjacency", attrname=a$attrname) @@ -210,6 +210,14 @@ ergm_edgecov_args <- function(name, nw, a){ } }else xm <- as.matrix(a$x) + # Check dimension + actual <- dim(xm) + expected <- + if(is.bipartite(nw)) c(nw %n% "bipartite", network.size(nw) - nw %n% "bipartite") + else rep(network.size(nw), 2) + + if(any(actual!=expected)) ergm_Init_stop("Dyadic covariate matrix has dimension ", actual[1], "x", actual[2], ", ", expected[1], "x", expected[2], " expected.") + cn <- if(!is.null(a$attrname)) paste(name, a$attrname, sep = ".") else paste(name, if(is.character(a$x)) a$x else deparse1(attr(a,"exprs")$x), sep = ".") diff --git a/man-roxygen/ergmTerm-x-attrname.R b/man-roxygen/ergmTerm-x-attrname.R index c73cbe25e..c8f1dd3cf 100644 --- a/man-roxygen/ergmTerm-x-attrname.R +++ b/man-roxygen/ergmTerm-x-attrname.R @@ -7,10 +7,19 @@ # # Copyright 2003-2023 Statnet Commons ################################################################################ -#' @param x,attrname either a square matrix of covariates, one for -#' each possible edge in the network, the name of a network -#' attribute of covariates, or a network; if the latter, or if the -#' network attribute named by `x` is itself a network, optional -#' argument `attrname` provides the name of the quantitative edge -#' attribute to use for covariate values (in this case, missing -#' edges in `x` are assigned a covariate value of zero). +#' @param x,attrname a specification for the dyadic covariate: either +#' one of the following, or the name of a network attribute +#' containing one of the following: \describe{ +#' +#' \item{a covariate matrix}{with dimensions \eqn{n \times n}{n*n} +#' for unipartite networks and \eqn{b \times (n-b)}{b*(n-b)} for +#' bipartite networks; `attrname`, if given, is used to construct +#' the term name.} +#' +#' \item{a network object}{with the same size and bipartitedness as +#' LHS; `attrname`, if given, provides the name of the +#' quantitative edge attribute to use for covariate values (in +#' this case, missing edges in `x` are assigned a covariate value +#' of zero).} +#' +#' } diff --git a/man/dyadcov-ergmTerm-5fba5404.Rd b/man/dyadcov-ergmTerm-5fba5404.Rd index 3d1dd9138..ac98941a6 100644 --- a/man/dyadcov-ergmTerm-5fba5404.Rd +++ b/man/dyadcov-ergmTerm-5fba5404.Rd @@ -8,13 +8,22 @@ # binary: dyadcov(x, attrname=NULL) } \arguments{ -\item{x, attrname}{either a square matrix of covariates, one for -each possible edge in the network, the name of a network -attribute of covariates, or a network; if the latter, or if the -network attribute named by \code{x} is itself a network, optional -argument \code{attrname} provides the name of the quantitative edge -attribute to use for covariate values (in this case, missing -edges in \code{x} are assigned a covariate value of zero).} +\item{x, attrname}{a specification for the dyadic covariate: either +one of the following, or the name of a network attribute +containing one of the following: \describe{ + +\item{a covariate matrix}{with dimensions \eqn{n \times n}{n*n} +for unipartite networks and \eqn{b \times (n-b)}{b*(n-b)} for +bipartite networks; \code{attrname}, if given, is used to construct +the term name.} + +\item{a network object}{with the same size and bipartitedness as +LHS; \code{attrname}, if given, provides the name of the +quantitative edge attribute to use for covariate values (in +this case, missing edges in \code{x} are assigned a covariate value +of zero).} + +}} } \description{ This term adds three statistics to the model, each equal to the sum of the diff --git a/man/edgecov-ergmTerm-1fb5ef19.Rd b/man/edgecov-ergmTerm-1fb5ef19.Rd index f0a6d67a6..c2c2935c1 100644 --- a/man/edgecov-ergmTerm-1fb5ef19.Rd +++ b/man/edgecov-ergmTerm-1fb5ef19.Rd @@ -11,13 +11,22 @@ # valued: edgecov(x, attrname=NULL, form="sum") } \arguments{ -\item{x, attrname}{either a square matrix of covariates, one for -each possible edge in the network, the name of a network -attribute of covariates, or a network; if the latter, or if the -network attribute named by \code{x} is itself a network, optional -argument \code{attrname} provides the name of the quantitative edge -attribute to use for covariate values (in this case, missing -edges in \code{x} are assigned a covariate value of zero).} +\item{x, attrname}{a specification for the dyadic covariate: either +one of the following, or the name of a network attribute +containing one of the following: \describe{ + +\item{a covariate matrix}{with dimensions \eqn{n \times n}{n*n} +for unipartite networks and \eqn{b \times (n-b)}{b*(n-b)} for +bipartite networks; \code{attrname}, if given, is used to construct +the term name.} + +\item{a network object}{with the same size and bipartitedness as +LHS; \code{attrname}, if given, provides the name of the +quantitative edge attribute to use for covariate values (in +this case, missing edges in \code{x} are assigned a covariate value +of zero).} + +}} \item{form}{character how to aggregate tie values in a valued ERGM} } diff --git a/tests/testthat/test-term-flexible.R b/tests/testthat/test-term-flexible.R index 85801a3e3..51e52e650 100644 --- a/tests/testthat/test-term-flexible.R +++ b/tests/testthat/test-term-flexible.R @@ -159,6 +159,16 @@ test_that("edges, either", { expect_summary(s.0, e.0, 203, -.9072) }) +test_that("edgecov, dimension check, unipartite", { + cov <- matrix(0, 18, 19) + expect_error(summary(samplike~edgecov(cov)), '.*Dyadic covariate matrix has dimension 18x19, 18x18 expected.*') +}) + +test_that("edgecov, dimension check, bipartite", { + cov <- matrix(0, 129, 129) + expect_error(summary(bipnw~edgecov(cov)), '.*Dyadic covariate matrix has dimension 129x129, 100x29 expected.*') +}) + #test_that("hamming, any", { # mat.d <- matrix(0,18,18) # mat.u <- matrix(0, 205, 205)