diff --git a/DESCRIPTION b/DESCRIPTION index 8518646a..136bf67d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -79,7 +79,9 @@ Collate: 'InitErgmTerm.bipartite.degree.R' 'InitErgmTerm.blockop.R' 'InitErgmTerm.coincidence.R' + 'InitErgmTerm.degfactorial.R' 'InitErgmTerm.dgw_sp.R' + 'InitErgmTerm.diversity.R' 'InitErgmTerm.extra.R' 'InitErgmTerm.indices.R' 'InitErgmTerm.interaction.R' diff --git a/R/InitErgmTerm.degfactorial.R b/R/InitErgmTerm.degfactorial.R new file mode 100644 index 00000000..0ea024e3 --- /dev/null +++ b/R/InitErgmTerm.degfactorial.R @@ -0,0 +1,85 @@ +#' @templateVar name degm1lfactorial +#' @title Sum of log-factorials of degrees of non-isolates minus 1 +#' @description This term adds one network statistic to the model, +#' equalling \eqn{\sum_{i=1}^n \mathbb{I}(d_i>0) \log(d_i - 1)!}. +#' +#' @usage +#' # binary: degm1lfactorial +#' +#' @template ergmTerm-general +#' +#' @concept undirected +InitErgmTerm.degm1lfactorial <- function(nw, arglist, ..., version=packageVersion("ergm")) { + a <- check.ErgmTerm(nw, arglist) + list(name="sum_lfactorial_degreem1", coef.names="ldegm1lfactorial", minval = 0) +} + + +#' @templateVar name b2degm1lfactorial +#' @title Sum of log-factorials of degrees of Mode-2 non-isolates minus 1 +#' @description This term adds one network statistic to the model, +#' equalling \eqn{\sum_{i=b+1}^n \mathbb{I}(d_i>0) \log(d_i - 1)!}. +#' +#' @usage +#' # binary: b2degm1lfactorial +#' +#' @template ergmTerm-general +#' +#' @concept undirected +#' @concept bipartite +InitErgmTerm.b2degm1lfactorial <- function(nw, arglist, ...) { + a <- check.ErgmTerm(nw, arglist, bipartite = TRUE) + list(name="sum_lfactorial_idegreem1", coef.names="b2degm1lfactorial", minval = 0) +} + + +#' @templateVar name b1degm1lfactorial +#' @title Sum of log-factorials of degrees of Mode-1 non-isolates minus 1 +#' @description This term adds one network statistic to the model, +#' equalling \eqn{\sum_{i=1}^b \mathbb{I}(d_i>0) \log(d_i - 1)!}. +#' +#' @usage +#' # binary: b1degm1lfactorial +#' +#' @template ergmTerm-general +#' +#' @concept undirected +#' @concept bipartite +InitErgmTerm.b1degm1lfactorial <- function(nw, arglist, ...) { + a <- check.ErgmTerm(nw, arglist, bipartite = TRUE) + list(name="sum_lfactorial_odegreem1", coef.names="b1degm1lfactorial", minval = 0) +} + + +#' @templateVar name idegm1lfactorial +#' @title Sum of log-factorials of indegrees of non-in-isolates minus 1 +#' @description This term adds one network statistic to the model, +#' equalling \eqn{\sum_{i=1}^n \mathbb{I}(id_i>0) \log(id_i - 1)!}. +#' +#' @usage +#' # binary: idegm1lfactorial +#' +#' @template ergmTerm-general +#' +#' @concept directed +InitErgmTerm.idegm1lfactorial <- function(nw, arglist, ...) { + a <- check.ErgmTerm(nw, arglist, directed = TRUE) + list(name="sum_lfactorial_idegreem1", coef.names="idegm1lfactorial", minval = 0) +} + + +#' @templateVar name odegm1lfactorial +#' @title Sum of log-factorials of outdegrees of non-out-isolates minus 1 +#' @description This term adds one network statistic to the model, +#' equalling \eqn{\sum_{i=1}^n \mathbb{I}(od_i>0) \log(od_i - 1)!}. +#' +#' @usage +#' # binary: odegm1lfactorial +#' +#' @template ergmTerm-general +#' +#' @concept directed +InitErgmTerm.odegm1lfactorial <- function(nw, arglist, ...) { + a <- check.ErgmTerm(nw, arglist, directed = TRUE) + list(name="sum_lfactorial_odegreem1", coef.names="odegm1lfactorial", minval = 0) +} diff --git a/R/InitErgmTerm.diversity.R b/R/InitErgmTerm.diversity.R new file mode 100644 index 00000000..692f8309 --- /dev/null +++ b/R/InitErgmTerm.diversity.R @@ -0,0 +1,304 @@ +#' @templateVar name nodecovrange +#' @title Range of covariate values for neighbors of a node +#' @description This term adds a single network statistic equalling +#' the sum over the nodes of the difference between the highest +#' value of a nodal covariate and its lower covariate. +#' +#' @usage +#' # binary: nodecovrange(attr) +#' +#' @template ergmTerm-attr +#' +#' @template ergmTerm-general +#' +#' @concept directed +#' @concept undirected +#' @concept quantitative nodal attribute +InitErgmTerm.nodecovrange<-function (nw, arglist, ...) { +### Check the network and arguments to make sure they are appropriate. + a <- check.ErgmTerm(nw, arglist, directed=NULL, bipartite=NULL, + varnames = c("attr"), + vartypes = c(ERGM_VATTR_SPEC), + defaultvalues = list(NULL), + required = c(TRUE)) +### Process the arguments + nodecov <- ergm_get_vattr(a$attr, nw, accept="numeric") + coef.names <- nodecov_names(nodecov, "nodecovrange") + list(name="nodecovrange", coef.names=coef.names, inputs=c(nodecov)) +} + + +#' @templateVar name nodeocovrange +#' @title Range of covariate values for out-neighbors of a node +#' +#' @usage +#' # binary: nodeocovrange(attr) +#' +#' @inherit nodecovrange-ergmTerm +#' @template ergmTerm-attr +#' +#' @template ergmTerm-general +#' +#' @concept directed +#' @concept quantitative nodal attribute +InitErgmTerm.nodeocovrange<-function (nw, arglist, ...) { +### Check the network and arguments to make sure they are appropriate. + a <- check.ErgmTerm(nw, arglist, directed=TRUE, bipartite=NULL, + varnames = c("attr"), + vartypes = c(ERGM_VATTR_SPEC), + defaultvalues = list(NULL), + required = c(TRUE)) +### Process the arguments + nodecov <- ergm_get_vattr(a$attr, nw, accept="numeric") + coef.names <- nodecov_names(nodecov, "nodeocovrange") + list(name="nodeocovrange", coef.names=coef.names, inputs=c(nodecov)) +} + + +#' @templateVar name nodeicovrange +#' @title Range of covariate values for in-neighbors of a node +#' +#' @usage +#' # binary: nodeicovrange(attr) +#' +#' @inherit nodecovrange-ergmTerm +#' @template ergmTerm-attr +#' +#' @template ergmTerm-general +#' +#' @concept directed +#' @concept quantitative nodal attribute +InitErgmTerm.nodeicovrange<-function (nw, arglist, ...) { +### Check the network and arguments to make sure they are appropriate. + a <- check.ErgmTerm(nw, arglist, directed=TRUE, bipartite=NULL, + varnames = c("attr"), + vartypes = c(ERGM_VATTR_SPEC), + defaultvalues = list(NULL), + required = c(TRUE)) +### Process the arguments + nodecov <- ergm_get_vattr(a$attr, nw, accept="numeric") + coef.names <- nodecov_names(nodecov, "nodeicovrange") + list(name="nodeicovrange", coef.names=coef.names, inputs=c(nodecov)) +} + + +#' @templateVar name b1covrange +#' @title Range of covariate values for neighbors of a mode-1 node +#' +#' @usage +#' # binary: nodecovrange(attr) +#' +#' @inherit nodecovrange-ergmTerm +#' @template ergmTerm-attr +#' +#' @template ergmTerm-general +#' +#' @concept bipartite +#' @concept quantitative nodal attribute +InitErgmTerm.b1covrange<-function (nw, arglist, ...) { +### Check the network and arguments to make sure they are appropriate. + a <- check.ErgmTerm(nw, arglist, directed=NULL, bipartite=TRUE, + varnames = c("attr"), + vartypes = c(ERGM_VATTR_SPEC), + defaultvalues = list(NULL), + required = c(TRUE)) +### Process the arguments + nodecov <- ergm_get_vattr(a$attr, nw, accept="numeric", bip="b2") + coef.names <- nodecov_names(nodecov, "b1covrange") + list(name="b1covrange", coef.names=coef.names, inputs=c(nodecov)) +} + + + +#' @templateVar name b2covrange +#' @title Range of covariate values for neighbors of a mode-2 node +#' +#' @usage +#' # binary: nodecovrange(attr) +#' +#' @inherit nodecovrange-ergmTerm +#' @template ergmTerm-attr +#' +#' @template ergmTerm-general +#' +#' @concept bipartite +#' @concept quantitative nodal attribute +InitErgmTerm.b2covrange<-function (nw, arglist, ...) { +### Check the network and arguments to make sure they are appropriate. + a <- check.ErgmTerm(nw, arglist, directed=NULL, bipartite=TRUE, + varnames = c("attr"), + vartypes = c(ERGM_VATTR_SPEC), + defaultvalues = list(NULL), + required = c(TRUE)) +### Process the arguments + nodecov <- ergm_get_vattr(a$attr, nw, accept="numeric", bip="b1") + coef.names <- nodecov_names(nodecov, "b2covrange") + list(name="nodeicovrange", coef.names=coef.names, inputs=c(nodecov)) +} + + + +.nodefactordistinct_impl <- function(deg, dir, bip, nw, arglist, ..., degname=deg){ + a <- check.ErgmTerm(nw, arglist, directed=dir, bipartite=bip, + varnames = c("attr", "levels"), + vartypes = c(ERGM_VATTR_SPEC, ERGM_LEVELS_SPEC), + defaultvalues = list(NULL, NULL), + required = c(TRUE, FALSE)) + + attr <- a$attr + levels <- a$levels + + nodecov <- if(NVL(bip, FALSE)) ergm_get_vattr(attr, nw, bip = c(b1="b2",b2="b1")[deg]) else ergm_get_vattr(attr, nw) + attrname <- attr(nodecov, "name") + u <- ergm_attr_levels(levels, nodecov, nw, levels = sort(unique(nodecov))) + + if (length(u)==0) { # Get outta here! (can happen if user passes attribute with one value) + return() + } + # Recode to numeric + nodepos <- match(nodecov,u,nomatch=0) + ### Construct the list to return + inputs <- c(max(nodepos), nodepos) + list(name=paste0(degname, "factordistinct"), #required + coef.names = paste(paste0(deg, "factordistinct"), paste(attrname,collapse="."), sep="."), #required + iinputs = inputs, + minval = 0 + ) +} + +#' @templateVar name nodefactordistinct +#' @title Number of distinct neighbor types +#' @description This term adds a single network statistic to the +#' model, counting, for each node, the number of distinct values of +#' the attribute found among its neighbors. +#' +#' @usage +#' # binary: nodefactordistinct(attr, levels=TRUE) +#' +#' @template ergmTerm-attr +#' @templateVar explain this optional argument controls which levels of the attribute +#' should be included and which should be excluded. +#' @template ergmTerm-levels-doco +#' +#' @template ergmTerm-general +#' +#' @concept directed +#' @concept undirected +#' @concept categorical nodal attribute +InitErgmTerm.nodefactordistinct<-function (nw, arglist, ...) { + a <- check.ErgmTerm(nw, arglist, + varnames = c("attr", "levels"), + vartypes = c(ERGM_VATTR_SPEC, ERGM_LEVELS_SPEC), + defaultvalues = list(NULL, NULL), + required = c(TRUE, FALSE), + dep.inform = list(FALSE, FALSE)) + .nodefactordistinct_impl("node", NULL, NULL, nw, arglist) +} + + +#' @templateVar name nodeofactordistinct +#' @title Number of distinct out-neighbor types +#' +#' @usage +#' # binary: nodeofactordistinct(attr, levels=TRUE) +#' +#' @inherit nodefactordistinct-ergmTerm +#' @template ergmTerm-attr +#' @templateVar explain this optional argument controls which levels of the attribute +#' should be included and which should be excluded. +#' @template ergmTerm-levels-doco +#' +#' @template ergmTerm-general +#' +#' @concept directed +#' @concept categorical nodal attribute +InitErgmTerm.nodeofactordistinct<-function (nw, arglist, ...) { + a <- check.ErgmTerm(nw, arglist, + varnames = c("attr", "levels"), + vartypes = c(ERGM_VATTR_SPEC, ERGM_LEVELS_SPEC), + defaultvalues = list(NULL, NULL), + required = c(TRUE, FALSE), + dep.inform = list(FALSE, FALSE)) + .nodefactordistinct_impl("nodeo", TRUE, NULL, nw, arglist) +} + + +#' @templateVar name nodeifactordistinct +#' @title Number of distinct in-neighbor types +#' +#' @usage +#' # binary: nodeifactordistinct(attr, levels=TRUE) +#' +#' @inherit nodefactordistinct-ergmTerm +#' @template ergmTerm-attr +#' @templateVar explain this optional argument controls which levels of the attribute +#' should be included and which should be excluded. +#' @template ergmTerm-levels-doco +#' +#' @template ergmTerm-general +#' +#' @concept directed +#' @concept categorical nodal attribute +InitErgmTerm.nodeifactordistinct<-function (nw, arglist, ...) { + a <- check.ErgmTerm(nw, arglist, + varnames = c("attr", "levels"), + vartypes = c(ERGM_VATTR_SPEC, ERGM_LEVELS_SPEC), + defaultvalues = list(NULL, NULL), + required = c(TRUE, FALSE), + dep.inform = list(FALSE, FALSE)) + .nodefactordistinct_impl("nodei", TRUE, NULL, nw, arglist) +} + + +#' @templateVar name b1factordistinct +#' @title Number of distinct neighbor types for the first node +#' +#' @usage +#' # binary: b1factordistinct(attr, levels=TRUE) +#' +#' @inherit nodefactordistinct-ergmTerm +#' @template ergmTerm-attr +#' @templateVar explain this optional argument controls which levels of the attribute +#' should be included and which should be excluded. +#' @template ergmTerm-levels-doco +#' +#' @template ergmTerm-general +#' +#' @concept bipartite +#' @concept categorical nodal attribute +InitErgmTerm.b1factordistinct<-function (nw, arglist, ...) { + a <- check.ErgmTerm(nw, arglist, + varnames = c("attr", "levels"), + vartypes = c(ERGM_VATTR_SPEC, ERGM_LEVELS_SPEC), + defaultvalues = list(NULL, NULL), + required = c(TRUE, FALSE), + dep.inform = list(FALSE, FALSE)) + .nodefactordistinct_impl("b1", NULL, TRUE, nw, arglist) +} + + +#' @templateVar name b2factordistinct +#' @title Number of distinct neighbor types for the second mode +#' +#' @usage +#' # binary: b2factordistinct(attr, levels=TRUE) +#' +#' @inherit nodefactordistinct-ergmTerm +#' @template ergmTerm-attr +#' @templateVar explain this optional argument controls which levels of the attribute +#' should be included and which should be excluded. +#' @template ergmTerm-levels-doco +#' +#' @template ergmTerm-general +#' +#' @concept bipartite +#' @concept categorical nodal attribute +InitErgmTerm.b2factordistinct<-function (nw, arglist, ...) { + a <- check.ErgmTerm(nw, arglist, + varnames = c("attr", "levels"), + vartypes = c(ERGM_VATTR_SPEC, ERGM_LEVELS_SPEC), + defaultvalues = list(NULL, NULL), + required = c(TRUE, FALSE), + dep.inform = list(FALSE, FALSE)) + .nodefactordistinct_impl("b2", NULL, TRUE, nw, arglist) +} diff --git a/man/b1covrange-ergmTerm-24a903d2.Rd b/man/b1covrange-ergmTerm-24a903d2.Rd new file mode 100644 index 00000000..5e9e57af --- /dev/null +++ b/man/b1covrange-ergmTerm-24a903d2.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.diversity.R +\name{b1covrange-ergmTerm} +\alias{b1covrange-ergmTerm} +\alias{InitErgmTerm.b1covrange} +\title{Range of covariate values for neighbors of a mode-1 node} +\usage{ +# binary: nodecovrange(attr) +} +\arguments{ +\item{attr}{a vertex attribute specification (see Specifying Vertex attributes and Levels (\code{?nodal_attributes}) for details.)} +} +\description{ +This term adds a single network statistic equalling +the sum over the nodes of the difference between the highest +value of a nodal covariate and its lower covariate. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "b1covrange", "subsection")} +} +\concept{bipartite} +\concept{quantitative nodal attribute} diff --git a/man/b1degm1lfactorial-ergmTerm-268d1fe0.Rd b/man/b1degm1lfactorial-ergmTerm-268d1fe0.Rd new file mode 100644 index 00000000..351352c9 --- /dev/null +++ b/man/b1degm1lfactorial-ergmTerm-268d1fe0.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.degfactorial.R +\name{b1degm1lfactorial-ergmTerm} +\alias{b1degm1lfactorial-ergmTerm} +\alias{InitErgmTerm.b1degm1lfactorial} +\title{Sum of log-factorials of degrees of Mode-1 non-isolates minus 1} +\usage{ +# binary: b1degm1lfactorial +} +\description{ +This term adds one network statistic to the model, +equalling \eqn{\sum_{i=1}^b \mathbb{I}(d_i>0) \log(d_i - 1)!}. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "b1degm1lfactorial", "subsection")} +} +\concept{bipartite} +\concept{undirected} diff --git a/man/b1factordistinct-ergmTerm-f897b95c.Rd b/man/b1factordistinct-ergmTerm-f897b95c.Rd new file mode 100644 index 00000000..940e3f37 --- /dev/null +++ b/man/b1factordistinct-ergmTerm-f897b95c.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.diversity.R +\name{b1factordistinct-ergmTerm} +\alias{b1factordistinct-ergmTerm} +\alias{InitErgmTerm.b1factordistinct} +\title{Number of distinct neighbor types for the first node} +\usage{ +# binary: b1factordistinct(attr, levels=TRUE) +} +\arguments{ +\item{attr}{a vertex attribute specification (see Specifying Vertex attributes and Levels (\code{?nodal_attributes}) for details.)} + +\item{levels}{this optional argument controls which levels of the attribute +attributes and Levels (\code{\link[=nodal_attributes]{?nodal_attributes}}) for details.)} +} +\description{ +This term adds a single network statistic to the +model, counting, for each node, the number of distinct values of +the attribute found among its neighbors. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "b1factordistinct", "subsection")} +} +\concept{bipartite} +\concept{categorical nodal attribute} diff --git a/man/b2covrange-ergmTerm-5e2bcc86.Rd b/man/b2covrange-ergmTerm-5e2bcc86.Rd new file mode 100644 index 00000000..7852704c --- /dev/null +++ b/man/b2covrange-ergmTerm-5e2bcc86.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.diversity.R +\name{b2covrange-ergmTerm} +\alias{b2covrange-ergmTerm} +\alias{InitErgmTerm.b2covrange} +\title{Range of covariate values for neighbors of a mode-2 node} +\usage{ +# binary: nodecovrange(attr) +} +\arguments{ +\item{attr}{a vertex attribute specification (see Specifying Vertex attributes and Levels (\code{?nodal_attributes}) for details.)} +} +\description{ +This term adds a single network statistic equalling +the sum over the nodes of the difference between the highest +value of a nodal covariate and its lower covariate. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "b2covrange", "subsection")} +} +\concept{bipartite} +\concept{quantitative nodal attribute} diff --git a/man/b2degm1lfactorial-ergmTerm-134e4482.Rd b/man/b2degm1lfactorial-ergmTerm-134e4482.Rd new file mode 100644 index 00000000..26dffe27 --- /dev/null +++ b/man/b2degm1lfactorial-ergmTerm-134e4482.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.degfactorial.R +\name{b2degm1lfactorial-ergmTerm} +\alias{b2degm1lfactorial-ergmTerm} +\alias{InitErgmTerm.b2degm1lfactorial} +\title{Sum of log-factorials of degrees of Mode-2 non-isolates minus 1} +\usage{ +# binary: b2degm1lfactorial +} +\description{ +This term adds one network statistic to the model, +equalling \eqn{\sum_{i=b+1}^n \mathbb{I}(d_i>0) \log(d_i - 1)!}. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "b2degm1lfactorial", "subsection")} +} +\concept{bipartite} +\concept{undirected} diff --git a/man/b2factordistinct-ergmTerm-076e6026.Rd b/man/b2factordistinct-ergmTerm-076e6026.Rd new file mode 100644 index 00000000..345dfbdb --- /dev/null +++ b/man/b2factordistinct-ergmTerm-076e6026.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.diversity.R +\name{b2factordistinct-ergmTerm} +\alias{b2factordistinct-ergmTerm} +\alias{InitErgmTerm.b2factordistinct} +\title{Number of distinct neighbor types for the second mode} +\usage{ +# binary: b2factordistinct(attr, levels=TRUE) +} +\arguments{ +\item{attr}{a vertex attribute specification (see Specifying Vertex attributes and Levels (\code{?nodal_attributes}) for details.)} + +\item{levels}{this optional argument controls which levels of the attribute +attributes and Levels (\code{\link[=nodal_attributes]{?nodal_attributes}}) for details.)} +} +\description{ +This term adds a single network statistic to the +model, counting, for each node, the number of distinct values of +the attribute found among its neighbors. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "b2factordistinct", "subsection")} +} +\concept{bipartite} +\concept{categorical nodal attribute} diff --git a/man/degm1lfactorial-ergmTerm-0f187aa0.Rd b/man/degm1lfactorial-ergmTerm-0f187aa0.Rd new file mode 100644 index 00000000..0cfe96b7 --- /dev/null +++ b/man/degm1lfactorial-ergmTerm-0f187aa0.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.degfactorial.R +\name{degm1lfactorial-ergmTerm} +\alias{degm1lfactorial-ergmTerm} +\alias{InitErgmTerm.degm1lfactorial} +\title{Sum of log-factorials of degrees of non-isolates minus 1} +\usage{ +# binary: degm1lfactorial +} +\description{ +This term adds one network statistic to the model, +equalling \eqn{\sum_{i=1}^n \mathbb{I}(d_i>0) \log(d_i - 1)!}. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "degm1lfactorial", "subsection")} +} +\concept{undirected} diff --git a/man/idegm1lfactorial-ergmTerm-4be755fd.Rd b/man/idegm1lfactorial-ergmTerm-4be755fd.Rd new file mode 100644 index 00000000..a325e9ca --- /dev/null +++ b/man/idegm1lfactorial-ergmTerm-4be755fd.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.degfactorial.R +\name{idegm1lfactorial-ergmTerm} +\alias{idegm1lfactorial-ergmTerm} +\alias{InitErgmTerm.idegm1lfactorial} +\title{Sum of log-factorials of indegrees of non-in-isolates minus 1} +\usage{ +# binary: idegm1lfactorial +} +\description{ +This term adds one network statistic to the model, +equalling \eqn{\sum_{i=1}^n \mathbb{I}(id_i>0) \log(id_i - 1)!}. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "idegm1lfactorial", "subsection")} +} +\concept{bipartite} +\concept{undirected} diff --git a/man/nodecovrange-ergmTerm-7ae91499.Rd b/man/nodecovrange-ergmTerm-7ae91499.Rd new file mode 100644 index 00000000..84bb2392 --- /dev/null +++ b/man/nodecovrange-ergmTerm-7ae91499.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.diversity.R +\name{nodecovrange-ergmTerm} +\alias{nodecovrange-ergmTerm} +\alias{InitErgmTerm.nodecovrange} +\title{Range of covariate values for neighbors of a node} +\usage{ +# binary: nodecovrange(attr) +} +\arguments{ +\item{attr}{a vertex attribute specification (see Specifying Vertex attributes and Levels (\code{?nodal_attributes}) for details.)} +} +\description{ +This term adds a single network statistic equalling +the sum over the nodes of the difference between the highest +value of a nodal covariate and its lower covariate. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "nodecovrange", "subsection")} +} +\concept{directed} +\concept{quantitative nodal attribute} +\concept{undirected} diff --git a/man/nodefactordistinct-ergmTerm-3445048c.Rd b/man/nodefactordistinct-ergmTerm-3445048c.Rd new file mode 100644 index 00000000..858e9651 --- /dev/null +++ b/man/nodefactordistinct-ergmTerm-3445048c.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.diversity.R +\name{nodefactordistinct-ergmTerm} +\alias{nodefactordistinct-ergmTerm} +\alias{InitErgmTerm.nodefactordistinct} +\title{Number of distinct neighbor types} +\usage{ +# binary: nodefactordistinct(attr, levels=TRUE) +} +\arguments{ +\item{attr}{a vertex attribute specification (see Specifying Vertex attributes and Levels (\code{?nodal_attributes}) for details.)} + +\item{levels}{this optional argument controls which levels of the attribute +attributes and Levels (\code{\link[=nodal_attributes]{?nodal_attributes}}) for details.)} +} +\description{ +This term adds a single network statistic to the +model, counting, for each node, the number of distinct values of +the attribute found among its neighbors. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "nodefactordistinct", "subsection")} +} +\concept{categorical nodal attribute} +\concept{directed} +\concept{undirected} diff --git a/man/nodeicovrange-ergmTerm-29a8edd7.Rd b/man/nodeicovrange-ergmTerm-29a8edd7.Rd new file mode 100644 index 00000000..12161e88 --- /dev/null +++ b/man/nodeicovrange-ergmTerm-29a8edd7.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.diversity.R +\name{nodeicovrange-ergmTerm} +\alias{nodeicovrange-ergmTerm} +\alias{InitErgmTerm.nodeicovrange} +\title{Range of covariate values for in-neighbors of a node} +\usage{ +# binary: nodeicovrange(attr) +} +\arguments{ +\item{attr}{a vertex attribute specification (see Specifying Vertex attributes and Levels (\code{?nodal_attributes}) for details.)} +} +\description{ +This term adds a single network statistic equalling +the sum over the nodes of the difference between the highest +value of a nodal covariate and its lower covariate. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "nodeicovrange", "subsection")} +} +\concept{directed} +\concept{quantitative nodal attribute} diff --git a/man/nodeifactordistinct-ergmTerm-25cbd312.Rd b/man/nodeifactordistinct-ergmTerm-25cbd312.Rd new file mode 100644 index 00000000..9b83912e --- /dev/null +++ b/man/nodeifactordistinct-ergmTerm-25cbd312.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.diversity.R +\name{nodeifactordistinct-ergmTerm} +\alias{nodeifactordistinct-ergmTerm} +\alias{InitErgmTerm.nodeifactordistinct} +\title{Number of distinct in-neighbor types} +\usage{ +# binary: nodeifactordistinct(attr, levels=TRUE) +} +\arguments{ +\item{attr}{a vertex attribute specification (see Specifying Vertex attributes and Levels (\code{?nodal_attributes}) for details.)} + +\item{levels}{this optional argument controls which levels of the attribute +attributes and Levels (\code{\link[=nodal_attributes]{?nodal_attributes}}) for details.)} +} +\description{ +This term adds a single network statistic to the +model, counting, for each node, the number of distinct values of +the attribute found among its neighbors. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "nodeifactordistinct", "subsection")} +} +\concept{categorical nodal attribute} +\concept{directed} diff --git a/man/nodeocovrange-ergmTerm-382e45c5.Rd b/man/nodeocovrange-ergmTerm-382e45c5.Rd new file mode 100644 index 00000000..b4373ea4 --- /dev/null +++ b/man/nodeocovrange-ergmTerm-382e45c5.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.diversity.R +\name{nodeocovrange-ergmTerm} +\alias{nodeocovrange-ergmTerm} +\alias{InitErgmTerm.nodeocovrange} +\title{Range of covariate values for out-neighbors of a node} +\usage{ +# binary: nodeocovrange(attr) +} +\arguments{ +\item{attr}{a vertex attribute specification (see Specifying Vertex attributes and Levels (\code{?nodal_attributes}) for details.)} +} +\description{ +This term adds a single network statistic equalling +the sum over the nodes of the difference between the highest +value of a nodal covariate and its lower covariate. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "nodeocovrange", "subsection")} +} +\concept{directed} +\concept{quantitative nodal attribute} diff --git a/man/nodeofactordistinct-ergmTerm-f159e5dc.Rd b/man/nodeofactordistinct-ergmTerm-f159e5dc.Rd new file mode 100644 index 00000000..c8dccc2b --- /dev/null +++ b/man/nodeofactordistinct-ergmTerm-f159e5dc.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.diversity.R +\name{nodeofactordistinct-ergmTerm} +\alias{nodeofactordistinct-ergmTerm} +\alias{InitErgmTerm.nodeofactordistinct} +\title{Number of distinct out-neighbor types} +\usage{ +# binary: nodeofactordistinct(attr, levels=TRUE) +} +\arguments{ +\item{attr}{a vertex attribute specification (see Specifying Vertex attributes and Levels (\code{?nodal_attributes}) for details.)} + +\item{levels}{this optional argument controls which levels of the attribute +attributes and Levels (\code{\link[=nodal_attributes]{?nodal_attributes}}) for details.)} +} +\description{ +This term adds a single network statistic to the +model, counting, for each node, the number of distinct values of +the attribute found among its neighbors. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "nodeofactordistinct", "subsection")} +} +\concept{categorical nodal attribute} +\concept{directed} diff --git a/man/odegm1lfactorial-ergmTerm-b8eb44b3.Rd b/man/odegm1lfactorial-ergmTerm-b8eb44b3.Rd new file mode 100644 index 00000000..dad04072 --- /dev/null +++ b/man/odegm1lfactorial-ergmTerm-b8eb44b3.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InitErgmTerm.degfactorial.R +\name{odegm1lfactorial-ergmTerm} +\alias{odegm1lfactorial-ergmTerm} +\alias{InitErgmTerm.odegm1lfactorial} +\title{Sum of log-factorials of outdegrees of non-out-isolates minus 1} +\usage{ +# binary: odegm1lfactorial +} +\description{ +This term adds one network statistic to the model, +equalling \eqn{\sum_{i=1}^n \mathbb{I}(od_i>0) \log(od_i - 1)!}. +} +\seealso{ +\code{\link{ergmTerm}} for index of model terms currently visible to the package. + +\Sexpr[results=rd,stage=render]{ergm:::.formatTermKeywords("ergmTerm", "odegm1lfactorial", "subsection")} +} +\concept{bipartite} +\concept{undirected} diff --git a/src/changestats_degfactorial.c b/src/changestats_degfactorial.c new file mode 100644 index 00000000..e07d8dcd --- /dev/null +++ b/src/changestats_degfactorial.c @@ -0,0 +1,20 @@ +#include "ergm_changestat.h" +#include "ergm_storage.h" + +#define mk_c_sum_lfactorial_degreem1(_LABEL_, _OUT_, _IN_) \ + \ + C_CHANGESTAT_FN(c_sum_lfactorial_ ## _LABEL_ ## degreem1){ \ + int echange=edgestate ? -1:+1; \ + \ + Vertex otd = 0, ntd = 0, ohd = 0, nhd = 0; \ + \ + if(_OUT_){otd = OUT_DEG[tail] + ( _IN_ ? IN_DEG[tail] : 0); ntd = otd + echange;} \ + if(_IN_){ohd = ( _OUT_ ? OUT_DEG[head] : 0) + IN_DEG[head]; nhd = ohd + echange;} \ + \ + CHANGE_STAT[0] += (ntd?lgammafn(ntd):0) - (otd?lgammafn(otd):0) \ + + (nhd?lgammafn(nhd):0) - (ohd?lgammafn(ohd):0); \ + } + +mk_c_sum_lfactorial_degreem1(, TRUE, TRUE); +mk_c_sum_lfactorial_degreem1(o, TRUE, FALSE); +mk_c_sum_lfactorial_degreem1(i, FALSE, TRUE); diff --git a/src/changestats_diversity.c b/src/changestats_diversity.c new file mode 100644 index 00000000..22bf47da --- /dev/null +++ b/src/changestats_diversity.c @@ -0,0 +1,100 @@ +#include "ergm_changestat.h" +#include "ergm_storage.h" + +#define mk_c_nodecovrange(_LABEL_, _OUT_, _IN_, _BSHIFT_) \ + C_CHANGESTAT_FN(c_ ## _LABEL_ ## covrange) { \ + if( _OUT_ ) { \ + double oldmin = R_PosInf, oldmax = R_NegInf, newmin = R_PosInf, newmax = R_NegInf; \ + \ + EXEC_THROUGH_OUTEDGES(tail, e, u, { \ + oldmin = MIN(oldmin, INPUT_PARAM[u-1 _BSHIFT_]); \ + oldmax = MAX(oldmax, INPUT_PARAM[u-1 _BSHIFT_]); \ + \ + if(!edgestate || u!=head){ \ + newmin = MIN(newmin, INPUT_PARAM[u-1 _BSHIFT_]); \ + newmax = MAX(newmax, INPUT_PARAM[u-1 _BSHIFT_]); \ + } \ + }); \ + \ + if(!edgestate){ \ + newmin = MIN(newmin, INPUT_PARAM[head-1 _BSHIFT_]); \ + newmax = MAX(newmax, INPUT_PARAM[head-1 _BSHIFT_]); \ + } \ + \ + CHANGE_STAT[0] += (isinf(newmax) ? 0 : newmax-newmin) - (isinf(oldmax) ? 0 : oldmax-oldmin); \ + } \ + \ + if( _IN_ ) { \ + double oldmin = R_PosInf, oldmax = R_NegInf, newmin = R_PosInf, newmax = R_NegInf; \ + \ + EXEC_THROUGH_INEDGES(head, e, u, { \ + oldmin = MIN(oldmin, INPUT_PARAM[u-1]); \ + oldmax = MAX(oldmax, INPUT_PARAM[u-1]); \ + \ + if(!edgestate || u!=tail){ \ + newmin = MIN(newmin, INPUT_PARAM[u-1]); \ + newmax = MAX(newmax, INPUT_PARAM[u-1]); \ + } \ + }); \ + \ + if(!edgestate){ \ + newmin = MIN(newmin, INPUT_PARAM[tail-1]); \ + newmax = MAX(newmax, INPUT_PARAM[tail-1]); \ + } \ + \ + CHANGE_STAT[0] += (isinf(newmax) ? 0 : newmax-newmin) - (isinf(oldmax) ? 0 : oldmax-oldmin); \ + } \ + } + +mk_c_nodecovrange(node, TRUE, TRUE,) +mk_c_nodecovrange(nodeo, TRUE, FALSE,) +mk_c_nodecovrange(nodei, FALSE, TRUE,) +mk_c_nodecovrange(b1, TRUE, FALSE, - BIPARTITE) + + +#define mk_nodefactordistinct(_LABEL_, _EFF_NODES_, _OUT_, _IN_, _BSHIFT_) \ + \ + I_CHANGESTAT_FN(i_ ## _LABEL_ ## factordistinct) { \ + unsigned int ncats = IINPUT_PARAM[0]; \ + \ + ALLOC_STORAGE(ncats*(_EFF_NODES_), unsigned int, freqs); \ + \ + EXEC_THROUGH_NET_EDGES(tail, head, e, { \ + if(_OUT_ && IINPUT_PARAM[head _BSHIFT_]) freqs[(tail-1)*ncats + IINPUT_PARAM[head _BSHIFT_] - 1]++; \ + if(_IN_ && IINPUT_PARAM[tail]) freqs[(head-1 _BSHIFT_)*ncats + IINPUT_PARAM[tail] - 1]++; \ + }); \ + } \ + \ + C_CHANGESTAT_FN(c_ ## _LABEL_ ## factordistinct) { \ + unsigned int ncats = IINPUT_PARAM[0]; \ + GET_STORAGE(unsigned int, freqs); \ + int change = edgestate ? -1 : +1; \ + if(_OUT_ && IINPUT_PARAM[head _BSHIFT_]) { \ + unsigned int oldfreq = freqs[(tail-1)*ncats + IINPUT_PARAM[head _BSHIFT_] - 1]; \ + unsigned int newfreq = oldfreq + change; \ + CHANGE_STAT[0] += (newfreq!=0) - (oldfreq!=0); \ + } \ + \ + if(_IN_ && IINPUT_PARAM[tail]) { \ + unsigned int oldfreq = freqs[(head-1 _BSHIFT_)*ncats + IINPUT_PARAM[tail] - 1]; \ + unsigned int newfreq = oldfreq + change; \ + CHANGE_STAT[0] += (newfreq!=0) - (oldfreq!=0); \ + } \ + } \ + \ + \ + U_CHANGESTAT_FN(u_ ## _LABEL_ ## factordistinct) { \ + unsigned int ncats = IINPUT_PARAM[0]; \ + GET_STORAGE(unsigned int, freqs); \ + int change = edgestate ? -1 : +1; \ + if(_OUT_ && IINPUT_PARAM[head _BSHIFT_]) \ + freqs[(tail-1)*ncats + IINPUT_PARAM[head _BSHIFT_] - 1] += change; \ + if(_IN_ && IINPUT_PARAM[tail]) \ + freqs[(head-1 _BSHIFT_)*ncats + IINPUT_PARAM[tail] - 1] += change; \ + } + +mk_nodefactordistinct(node, N_NODES, TRUE, TRUE,) +mk_nodefactordistinct(nodeo, N_NODES, TRUE, FALSE,) +mk_nodefactordistinct(nodei, N_NODES, FALSE, TRUE,) +mk_nodefactordistinct(b1, BIPARTITE, TRUE, FALSE, - BIPARTITE) +mk_nodefactordistinct(b2, N_NODES-BIPARTITE, FALSE, TRUE, - BIPARTITE) diff --git a/tests/testthat/test-ergm-term-doc.R b/tests/testthat/test-ergm-term-doc.R index 35ae473a..decaa8e3 100644 --- a/tests/testthat/test-ergm-term-doc.R +++ b/tests/testthat/test-ergm-term-doc.R @@ -32,14 +32,14 @@ test_that("test search ergm term", { # search using a bipartite net as a template myNet<-network.initialize(5,bipartite=3,directed=FALSE) - expect_equal(length(search.ergmTerms(net=myNet)), 31) + expect_equal(length(search.ergmTerms(net=myNet)), 35) - expect_equal(length(search.ergmTerms(keywords = 'bipartite', packages='ergm')), 32) + expect_equal(length(search.ergmTerms(keywords = 'bipartite', packages='ergm')), 40) expect_gt(length(search.ergmTerms(name = 'b2factor', packages='ergm')), 0) expect_equal(length(search.ergmTerms(name = 'b3factor', packages='ergm')), 0) - expect_equal(length(search.ergmTerms(keywords = 'bipartite', packages='ergm')), 32) + expect_equal(length(search.ergmTerms(keywords = 'bipartite', packages='ergm')), 40) ## expect_gt(length(search.ergmTerms(keywords = 'valued')), 44) expect_equal(length(search.ergmTerms(keywords = 'valued', packages='ergm')), 44) diff --git a/tests/testthat/test-term-degfactorial.R b/tests/testthat/test-term-degfactorial.R new file mode 100644 index 00000000..81897bed --- /dev/null +++ b/tests/testthat/test-term-degfactorial.R @@ -0,0 +1,43 @@ +degm1lfactorial <- function(d){ + d <- d-1 + sum(lfactorial(d[d>=0])) +} + +data(florentine) + +test_that("degm1lfactorial summary", { + expect_equal(summary(flomarriage~degm1lfactorial), + degm1lfactorial(summary(flomarriage~sociality(nodes=TRUE))), + ignore_attr = TRUE) +}) + +n <- 20 +b <- 5 +nw0 <- network.initialize(n, bipartite = b, directed = FALSE) +nw1 <- simulate(nw0 ~ edges, coef = 0) + +test_that("b1degm1lfactorial summary", { + expect_equal(summary(nw1~b1degm1lfactorial), + degm1lfactorial(summary(nw1~b1sociality(nodes=TRUE))), + ignore_attr = TRUE) +}) + +test_that("b2degm1lfactorial summary", { + expect_equal(summary(nw1~b2degm1lfactorial), + degm1lfactorial(summary(nw1~b2sociality(nodes=TRUE))), + ignore_attr = TRUE) +}) + +data(sampson) + +test_that("odegm1lfactorial summary", { + expect_equal(summary(samplike~odegm1lfactorial), + degm1lfactorial(summary(samplike~sender(nodes=TRUE))), + ignore_attr = TRUE) +}) + +test_that("idegm1lfactorial summary", { + expect_equal(summary(samplike~idegm1lfactorial), + degm1lfactorial(summary(samplike~receiver(nodes=TRUE))), + ignore_attr = TRUE) +}) diff --git a/tests/testthat/test-term-diversity.R b/tests/testthat/test-term-diversity.R new file mode 100644 index 00000000..21181b2c --- /dev/null +++ b/tests/testthat/test-term-diversity.R @@ -0,0 +1,112 @@ +diversity <- function(nw, a, which = c("u", "i", "o", "1", "2"), stat = c("range", "distinct")){ + which <- match.arg(which) + stat <- match.arg(stat) + stat <- switch(stat, + range = function(x) diff(range(x, na.rm=TRUE)), + distinct = function(x) length(na.omit(unique(x)))) + + m <- as.matrix(nw) + w <- switch(which, + u =, + i =, + o = nw %v% a, + `1` = (nw %v% a)[-seq_len(nw%n%"bipartite")], + `2` = (nw %v% a)[seq_len(nw%n%"bipartite")]) + + if(which %in% c("o","1")) m <- t(m) + + r <- suppressWarnings(apply(ifelse(m, w, NA), 2, stat)) + sum(r[!is.infinite(r) & !is.na(r)]) +} + +data(florentine) + +test_that("nodecovrange summary", { + expect_equal(summary(flomarriage~nodecovrange("wealth")), + diversity(flomarriage, "wealth", "u", "range"), + ignore_attr = TRUE) +}) + +n <- 20 +b <- 5 + +nw0 <- network.initialize(n, bipartite = b, directed = FALSE) +nw0 %v% "b1" <- c(rnorm(b), rep(NA, n-b)) +nw0 %v% "b2" <- c(rep(NA, b), rnorm(n-b)) +nw1 <- simulate(nw0 ~ edges, coef = 0) + +test_that("b1covrange summary", { + expect_equal(summary(nw1~b1covrange("b2")), + diversity(nw1, "b2", "1", "range"), + ignore_attr = TRUE) +}) + +test_that("b2covrange summary", { + expect_equal(summary(nw1~b2covrange("b1")), + diversity(nw1, "b1", "2", "range"), + ignore_attr = TRUE) +}) + +data(sampson) +samplike %v% "w" <- rnorm(network.size(samplike)) + +test_that("nodeocovrange summary", { + expect_equal(summary(samplike~nodeocovrange("w")), + diversity(samplike, "w", "o", "range"), + ignore_attr = TRUE) +}) + +test_that("nodeicovrange summary", { + expect_equal(summary(samplike~nodeicovrange("w")), + diversity(samplike, "w", "i", "range"), + ignore_attr = TRUE) +}) + + +flomarriage %v% "c" <- sample.int(5, network.size(flomarriage), replace=TRUE) + +test_that("nodefactordistinct summary", { + expect_equal(summary(flomarriage~nodefactordistinct("c")), + diversity(flomarriage, "c", "u", "distinct"), + ignore_attr = TRUE) +}) + +test_that("nodeofactordistinct summary", { + expect_equal(summary(samplike~nodeofactordistinct("group")), + diversity(samplike, "group", "o", "distinct"), + ignore_attr = TRUE) +}) + +test_that("nodefactordistinct summary", { + expect_equal(summary(flomarriage~nodefactordistinct("c")), + diversity(flomarriage, "c", "u", "distinct"), + ignore_attr = TRUE) +}) + +test_that("nodeifactordistinct summary", { + expect_equal(summary(samplike~nodeifactordistinct("group")), + diversity(samplike, "group", "i", "distinct"), + ignore_attr = TRUE) +}) + + +n <- 20 +b <- 5 + +nw0 <- network.initialize(n, bipartite = b, directed = FALSE) +nw0 %v% "b1" <- c(sample.int(3, b, TRUE), rep(NA, n-b)) +nw0 %v% "b2" <- c(rep(NA, b), sample.int(3, n-b, TRUE)) +nw1 <- simulate(nw0 ~ edges, coef = 0) + + +test_that("b1factordistinct summary", { + expect_equal(summary(nw1~b1factordistinct("b2")), + diversity(nw1, "b2", "1", "distinct"), + ignore_attr = TRUE) +}) + +test_that("b2factordistinct summary", { + expect_equal(summary(nw1~b2factordistinct("b1")), + diversity(nw1, "b1", "2", "distinct"), + ignore_attr = TRUE) +})