nwergm

Exponential-family random graph model (ERGM) estimation

Syntax

nwergm
[netname]
,
edges
[covariate_effects
bipartite_effects
gw_effects
degree_effects
triad_effects
directed_covariate_effects
star_range_effects
sharedpartner_effects
triad_effects_directed
nodelevel_effects
estimation_control]

Required

   
edges Include the edges term (density/intercept); required

Node and dyadic covariate effects

   
mutual Reciprocated-tie count; directed networks only
nodematch(varlist) Pooled homophily on each listed categorical node attribute (exact match, one coefficient per variable)
nodematchdiff(varlist) Differential homophily: one coefficient PER DISTINCT LEVEL of each listed attribute, rather than pooled across levels
nodecov(varlist) Continuous node covariate main effect (sum over tie endpoints)
nodeicov(varlist) Directed receiver-covariate effect; directed networks only
nodeocov(varlist) Directed sender-covariate effect; directed networks only
edgecov(netname) Dyadic covariate effect, taken from an already-loaded network’s own tie values
absdist(varlist) Absolute-difference effect on a continuous node covariate: sum over ties of |x_i - x_j|
nodefactor(varlist) One coefficient per NON-BASE distinct level of each listed categorical attribute (the lowest-sorted level is omitted, matching R ergm’s own default, to avoid exact collinearity with edges), each counting total degree among nodes at that level
nodemix(varlist) Full categorical mixing matrix: one coefficient per distinct unordered pair of levels of each listed attribute

Two-mode (bipartite) effects

   
bcov1(varlist) Bipartite (two-mode) networks only: the b1cov() term from R’s own ergm package (renamed to bcov1() because Stata’s syntax command rejects an option name with a digit followed by a letter, e.g. b1cov) - continuous node covariate main effect for the MODE-1 endpoint only (sum, over ties, of the mode-1 endpoint’s own covariate value; the mode-2 endpoint’s value is never added). Reported coefficient name keeps R’s own b1cov_varname spelling
bcov2(varlist) Bipartite networks only: the b2cov() term - the bcov1() mirror for the MODE-2 endpoint. Reported coefficient name: b2cov_varname
bfactor1(varlist) Bipartite networks only: the b1factor() term - one coefficient per NON-BASE distinct level of each listed categorical attribute (lowest-sorted level omitted, same convention as nodefactor()), each counting the number of ties whose MODE-1 endpoint carries that level (the mode-2 endpoint never gets credit, unlike nodefactor()’s own both-endpoints convention). Reported coefficient name: b1factor_varname_level
bfactor2(varlist) Bipartite networks only: the b2factor() term - the bfactor1() mirror for the MODE-2 endpoint. Reported coefficient name: b2factor_varname_level
bdegree1(numlist) Bipartite networks only: the b1degree() term - one coefficient per listed degree value, counting the number of MODE-1 nodes with that exact (total) degree (the mode-2 endpoint never contributes). Dyad-DEPENDENT (needs method(mcmle)), unlike bcov1()/bfactor1(). Reported coefficient name: b1degree_d
bdegree2(numlist) Bipartite networks only: the b2degree() term - the bdegree1() mirror for the MODE-2 endpoint
bstar1(numlist) Bipartite networks only: the b1star() term - one coefficient per listed k, counting the number of distinct k-stars centered on a MODE-1 node (C(degree,k) summed over mode-1 nodes only). Dyad-DEPENDENT (needs method(mcmle)). Note: bstar1(1) equals bstar2(1) equals edges (R ergm’s own documented identity). Reported coefficient name: b1star_k
bstar2(numlist) Bipartite networks only: the b2star() term - the bstar1() mirror for the MODE-2 endpoint
bnodematch1(varlist) Bipartite networks only: the b1nodematch() term - pooled homophily (default-parameter scope: no diff()/alpha()/beta()/byb2attr()) on each listed categorical attribute, counting only ties whose MODE-1 endpoint carries the matching level. Dyad-DEPENDENT (needs method(mcmle)), unlike bcov1()/bfactor1(). Reported coefficient name: b1nodematch_varname
bnodematch2(varlist) Bipartite networks only: the b2nodematch() term - the bnodematch1() mirror for the MODE-2 endpoint. Reported coefficient name: b2nodematch_varname
bgwdegree1(real) Bipartite networks only: the gwb1degree() term - geometrically weighted degree, fixed decay, counting only MODE-1 nodes’ own degree. Dyad-DEPENDENT (needs method(mcmle)); no curved (estimated-decay) counterpart yet, unlike plain gwdegree()/gwdegreefree(). Reported coefficient name: bgwdegree1_decay
bgwdegree2(real) Bipartite networks only: the gwb2degree() term - the bgwdegree1() mirror for the MODE-2 endpoint. Reported coefficient name: bgwdegree2_decay

Geometrically weighted effects

   
gwesp(real) Geometrically weighted edgewise shared partners, fixed decay; undirected (UTP) or directed (shared-partner definition set by type(), default OTP)
gwespfree(real) Geometrically weighted edgewise shared partners with an ESTIMATED (curved) decay parameter; undirected (UTP), or directed (shared-partner definition set by type(), default OTP - all five of OTP/ITP/OSP/ISP/RTP supported). The argument is only a starting value for decay, not a fixed value. Both method(mple) and method(mcmle) are supported (default mcmle, as for any other dyad-dependent term - see method() below) - reports gwesp_weight/gwesp_decay in place of a single gwesp() coefficient. Cannot be combined with gwesp(), esp(), or another curved term
gwdegreefree(real) Geometrically weighted degree with an ESTIMATED (curved) decay parameter, undirected networks only; the argument is only a starting value for decay, not a fixed value. Both method(mple) and method(mcmle) are supported (default mcmle) - reports gwdegree_weight/gwdegree_decay in place of a single gwdegree() coefficient. Cannot be combined with gwdegree(), degree(), or another curved term
gwdspfree(real) Geometrically weighted dyadwise shared partners with an ESTIMATED (curved) decay parameter, undirected networks only; the argument is only a starting value for decay, not a fixed value. Both method(mple) and method(mcmle) are supported (default mcmle) - reports gwdsp_weight/gwdsp_decay in place of a single gwdsp() coefficient. Cannot be combined with gwdsp(), dsp(), or another curved term
gwodegreefree(real) Geometrically weighted out-degree with an ESTIMATED (curved) decay parameter, directed networks only; the argument is only a starting value for decay, not a fixed value. Both method(mple) and method(mcmle) are supported (default mcmle) - reports gwodegree_weight/gwodegree_decay in place of a single gwodegree() coefficient. Cannot be combined with gwodegree(), odegree(), or another curved term
gwidegreefree(real) Geometrically weighted in-degree with an ESTIMATED (curved) decay parameter, directed networks only; the argument is only a starting value for decay, not a fixed value. Both method(mple) and method(mcmle) are supported (default mcmle) - reports gwidegree_weight/gwidegree_decay in place of a single gwidegree() coefficient. Cannot be combined with gwidegree(), idegree(), or another curved term
gwnspfree(real) Geometrically weighted nonedgewise shared partners with an ESTIMATED (curved) decay parameter, undirected networks only; the argument is only a starting value for decay, not a fixed value. Both method(mple) and method(mcmle) are supported (default mcmle) - reports gwnsp_weight/gwnsp_decay in place of a single gwnsp() coefficient. Cannot be combined with gwnsp() or another curved term
gwdsp(real) Geometrically weighted dyadwise shared partners, fixed decay; undirected (UTP) or directed (see type())
gwdegree(real) Geometrically weighted degree, fixed decay
gwodegree(real) Geometrically weighted out-degree, fixed decay; directed networks only
gwidegree(real) Geometrically weighted in-degree, fixed decay; directed networks only
gwnsp(real) Geometrically weighted NONedgewise (untied-dyad) shared partners, fixed decay; undirected (UTP) or directed (see type()). Satisfies gwdsp = gwesp + gwnsp

Degree-distribution effects

   
degree(numlist) One coefficient per listed degree value: count of nodes with that exact (total) degree; undirected only
odegree(numlist) One coefficient per listed value: count of nodes with that exact out-degree; directed networks only
idegree(numlist) One coefficient per listed value: count of nodes with that exact in-degree; directed networks only
concurrent Count of nodes with (total) degree 2 or higher; undirected only

Triad-closure effects

   
triangle Count of triangles (mutually tied triples); undirected only
ctriple Count of cyclic triples ((i->j),(j->k),(k->i)); directed networks only

Directed covariate effects

   
nodeofactor(varlist) Directed analogue of nodefactor(): one coefficient per NON-BASE distinct level, each counting OUT-degree among nodes at that level; directed networks only
nodeifactor(varlist) Directed analogue of nodefactor(): one coefficient per NON-BASE distinct level, each counting IN-degree among nodes at that level; directed networks only

Star and degree-range effects

   
kstar(numlist) One coefficient per listed k value: count of k-stars ((total) degree choose k, summed over nodes); undirected only
ostar(numlist) One coefficient per listed k value: count of out-k-stars; directed networks only
istar(numlist) One coefficient per listed k value: count of in-k-stars; directed networks only
degrange(numlist) Semi-open-interval degree count: one coefficient per FROM value in this numlist, counting nodes with (total) degree in [from,to); pair with degrangeto(); undirected only
degrangeto(numlist) TO values pairing with degrange(), same order/length; omit for an open-ended upper bound
odegrange(numlist) Semi-open-interval OUT-degree count, paired with odegrangeto(); directed networks only
odegrangeto(numlist) TO values pairing with odegrange()
idegrange(numlist) Semi-open-interval IN-degree count, paired with idegrangeto(); directed networks only
idegrangeto(numlist) TO values pairing with idegrange()

Shared-partner count effects

   
esp(numlist) One coefficient per listed d value: count of TIED dyads with exactly d shared partners (fixed, non-geometric alternative to gwesp()); undirected (UTP) or directed (see type())
dsp(numlist) One coefficient per listed d value: count of ALL dyads (tied or not) with exactly d shared partners (fixed, non-geometric alternative to gwdsp()); undirected (UTP) or directed (see type()). An EXHAUSTIVE d-range (covering every shared-partner value a toggle can produce) is exactly collinear across its own columns - list a subset, not every achievable value
type(OTP\|ITP\|OSP\|ISP\|RTP) Shared-partner definition used by every gwesp()/gwdsp()/gwnsp()/esp()/dsp()/gwespfree() term in the model, on a DIRECTED network only (default OTP; silently ignored, matching R ergm’s own behaviour, when netname is undirected - see the Remarks section below for the five definitions)

Triad-closure effects (directed)

   
transitiveties Count of TIED arcs i->j for which there also exists a two-path i->k->j (an existence/threshold indicator, not a count - contrast with gwesp()/esp()); directed networks only
cyclicalties Count of TIED arcs i->j for which there also exists a return two-path j->k->i, closing a directed 3-cycle; directed networks only

Dyadic covariate and node-level effects

   
hamming(netname) Hamming distance to a reference network: count of dyads whose tie state disagrees with the same network’s
sender One coefficient per node (except a base node) equal to that node’s own out-degree; directed networks only
receiver One coefficient per node (except a base node) equal to that node’s own in-degree; directed networks only

Estimation control

   
method(mple\|mcmle) Estimation method; default mcmle unless the model is dyad-independent, in which case MPLE already is the MLE
offset(coefname # [coefname # ...]) Hold one or more named coefficients fixed at a given value rather than estimating them, matching R ergm’s own offset() formula wrapper. coefname must be a coefficient this model would otherwise report (an option must still be typed to register the term, e.g. triangle, before offset(triangle #) can fix its own coefficient - offset() names an EXISTING coefficient, it does not add a second copy of the term). Works with both method(mple) and method(mcmle). At least one coefficient in the model must remain free. Not currently supported for a curved (free-decay) term’s own weight/decay. The fixed coefficient is reported at exactly the given value with standard error exactly 0 (matching R’s own real output) and a zero row/column in e(V) - see Remarks below
mcmcburnin(int) MCMC burn-in steps per simulation; default 3,000
mcmcinterval(int) MCMC steps between recorded draws; default 50
mcmcsamplesize(int) Number of recorded MCMC draws per simulation; default 3,000
mcmleiterations(int) Maximum MCMLE outer iterations; default 20
proposal(uniform\|tnt) Metropolis-Hastings proposal; default tnt. Both have a masked variant when freedyads() or blockdiag() is given
freedyads(netname) Restrict the dyad space to fit (see Remarks): netname’s own ties mark which dyads of the network being fit are free to vary during MCMC; every dyad NOT tied in netname is held fixed at its observed value for the rest of the fit (R ergm’s own fixallbut() constraint). Compatible with both proposal(uniform) and proposal(tnt), and native (C)-accelerated when otherwise eligible. See Limitations (v1 scope) below
blockdiag(varname) Restrict the dyad space to fit (see Remarks): only dyads sharing the same value of varname are free to vary during MCMC; every cross-value dyad is held fixed at its observed value for the rest of the fit (R ergm’s own blockdiag() constraint). Cannot be combined with freedyads(). Compatible with both proposal(uniform) and proposal(tnt), and native (C)-accelerated when otherwise eligible
seed(int) Set the random-number seed before simulating (for reproducibility)
verbose Show MPLE/MCMLE iteration detail
spcache Enable the incremental shared-partner cache for gwesp()/gwdsp()/gwnsp()/esp()/dsp()/triangle/ctriple on an undirected network; OFF by default because direct benchmarking found it a net LOSS below roughly average degree 30-40 (the common case) and a net win only above that - enable only for denser undirected networks; no effect on a directed network or without any of those terms
fixdensity Hold the total tie count fixed during MCMC (R ergm’s own constraints=~edges), via a compound tie/non-tie swap proposal rather than the ordinary single-dyad toggle; native (C)-accelerated when otherwise eligible. Requires method(mcmle) and at least one term besides edges (which is dropped, not estimated, under this constraint - see Remarks). Cannot currently be combined with freedyads()/blockdiag() - v1 supports one dyad-space constraint at a time
nonative Force the pure-Mata backend even on an otherwise native-eligible model - an explicit escape hatch for testing or direct comparison against the native (C) backend; not needed for ordinary use, since nwergm already picks the native backend automatically whenever a model qualifies
nomcmcsample Skip posting e(mcmcsample) (method(mcmle) only). Populating this matrix from Mata is the single slowest step for a fit with a large mcmcsamplesize() - a genuine Stata matrix-engine cost at bulk-data scale (confirmed by direct timing: over 30 seconds at 100,000 rows), not something estat mcmcdiag’s own consumption of it can be blamed for or sped up (reading the already-posted matrix back is fast regardless of size - the cost is entirely in creating it in the first place). Specify nomcmcsample when fitting with an unusually large mcmcsamplesize() and you do not need estat mcmcdiag or to inspect the raw sample directly - the coefficient table, standard errors, and every other stored result are completely unaffected

Description

nwergm fits an exponential-family random graph model (ERGM) to the network(s) in netname (default: the currently set network) using a fully native Stata/Mata implementation - no R or other external statistical software is called at any point, at estimation time or otherwise. Statnet’s mature ergm R package was studied in detail as a behavioural and architectural reference during development (see statnet.org) and used, during development only, to certify nwergm’s own independently-written implementation against real reference output; see Provenance below.

nwergm implements a substantial, independently-certified core of Statnet’s own ergm term surface and estimation machinery: a term registry, Metropolis-Hastings simulation with a genuine tie/no-tie proposal, maximum pseudolikelihood estimation, and Monte Carlo maximum likelihood estimation, backed by an effect library covering the full node-covariate family, dyadic covariates, the geometrically weighted family (including directed shared-partner support and curved/free-decay estimation under both method(mple) and method(mcmle)), fixed shared-partner counts, the complete degree-distribution family, and directed triad-closure terms - see Limitations below for the complete current list, plus a narrow term family for two-mode (bipartite) networks. What still sets nwergm apart from full parity is scope, not term count: a wider bipartite term family and constraints beyond the free binary dyad space are each a genuine architectural addition rather than another term to add, and are not yet supported.

method() selects the estimation method. If every requested term is dyad-independent (the node-covariate family - edges, nodematch(), nodematchdiff(), nodecov(), nodeicov()/nodeocov(), absdist(), nodefactor(), nodeofactor()/nodeifactor(), nodemix(), sender, receiver - plus the dyadic-covariate terms edgecov()/hamming()) and no dyad-DEPENDENT term (mutual, any geometrically weighted term, any degree-distribution term, triangle, ctriple, transitiveties, cyclicalties, esp(), or dsp()) is present, maximum pseudolikelihood is the maximum likelihood estimate - nwergm detects this automatically and reports method(mple) results directly (labeled as such, not as full ERGM MLE) without ever running MCMC. Otherwise the default is method(mcmle): pseudolikelihood is used only as the starting value for Monte Carlo maximum likelihood. This applies equally to a curved (free-decay) term (gwespfree() and its five counterparts) - the curved MPLE fit is the method(mcmle) starting point, and MCMLE then refines it using R ergm’s own steplength/convergence approach (Hummel, Hunter, and Handcock 2012).

A curved decay parameter can be weakly identified on a small or sparse network, in which case the fit legitimately converges to a boundary solution - decay near 0 (near-complete collapse to a single shared-partner-count effect) or, less often, a large decay (near-complete insensitivity to shared-partner count beyond the first). This is a property of the statistical model, not a bug: R’s own ergm converges to the same kind of boundary solution on the same data, and can fail to converge at all on a genuinely poorly-identified network (occasionally so does nwergm, reported honestly as a non-converged fit rather than a plausible-looking wrong number - see e(converged) below). A large standard error on the decay coefficient is the usual sign this has happened; consider a longer mcmcburnin(), a larger mcmcsamplesize(), a different starting decay, or a fixed-decay (gwesp() etc.) or non-curved model instead.

offset() fixes a named coefficient at a known value instead of estimating it - useful for imposing a theoretically-motivated effect size, reproducing a published model exactly, or holding a nuisance term constant. Internally: for method(mple), the fixed term’s own known contribution is passed to the underlying logistic regression as a GLM offset (the standard mechanism for a fixed-coefficient term in any exponential-family regression), and only the remaining coefficients are estimated; for method(mcmle), the Newton step is restricted to the free coefficients only, while the fixed term’s own contribution still fully participates in MCMC sampling (fixing a coefficient does not remove its term from the model - the network is still simulated as if that effect were really present at the given strength). Multiple coefficients may be fixed in one model: offset(mutual 2 gwesp_weight 0.5).

Examples

. nwwebuse florentine, nwclear
. nwergm flomarriage, edges
. nwergm flomarriage, edges nodecov(wealth)
. nwergm flomarriage, edges gwesp(.5)

Supported network types

Binary: yes (only) - MPLE/MCMLE estimation here is for a binary tie-formation model; a valued network’s own tie values are not used as an outcome (no weighted ERGM family is implemented). Directed: yes, most terms have both directed and undirected forms (see the term list). Weighted: not applicable (see Binary). Signed: not applicable. Two-mode: yes, undirected only - a narrow term family so far (edges, bcov1()/bcov2()/bfactor1()/bfactor2(), bdegree1()/bdegree2()/bstar1()/bstar2(), bnodematch1()/bnodematch2(), bgwdegree1()/bgwdegree2()); see Limitations below.

Stored results

Scalars

  • e(N) number of dyads
  • e(nodes) number of nodes
  • e(ties) number of observed ties
  • e(converged) 1 if MCMLE’s own convergence test was satisfied (method(mcmle) only)
  • e(mcmle_iterations) number of MCMLE outer iterations run (method(mcmle) only)
  • e(mcmc_acceptrate) Metropolis-Hastings acceptance rate, final simulation (method(mcmle) only)
  • e(mcmc_burnin) MCMC burn-in steps used (method(mcmle) only)
  • e(mcmc_interval) MCMC thinning interval requested (method(mcmle) only)
  • e(mcmc_interval_final) MCMC thinning interval actually used for the last iteration - may
  • exceed e(mcmc_interval) if the adaptive-interval mechanism grew it
  • to reach an adequate effective sample size (method(mcmle) only)
  • e(mcmc_samplesize) MCMC recorded-draw count used (method(mcmle) only)
  • e(native) 1 if the native (C) backend was used for this run (the MCMC sampler
  • for method(mcmle); the MPLE design-matrix build for method(mple)),
  • 0 if the Mata implementation ran instead - purely informational,
  • see Performance below

Macros

  • e(cmd) nwergm
  • e(title) title of estimation
  • e(depvar) name of the estimated network
  • e(method) mple or mcmle
  • e(directed) true/false
  • e(proposal) Metropolis-Hastings proposal used (method(mcmle) only)
  • e(estat_cmd) nwergm_estat (postestimation dispatch)

Matrices

  • e(b) coefficient vector
  • e(V) variance-covariance matrix
  • e(mcmcsample) final simulation’s sufficient-statistic draws, samplesize x nparam (method(mcmle) only)

References

Hunter, D.R., Handcock, M.S., Butts, C.T., Goodreau, S.M., Morris, M. (2008). ergm: A Package to Fit, Simulate and Diagnose Exponential-Family Models for Networks. Journal of Statistical Software, 24(3), 1-29.

Hunter, D.R., Handcock, M.S. (2006). Inference in curved exponential family models for networks. Journal of Computational and Graphical Statistics, 15(3), 565-583. (MPLE)

Hunter, D.R. (2007). Curved exponential family models for social networks. Social Networks, 29(2), 216-230. (GWESP/GWDEGREE)

Morris, M., Handcock, M.S., Hunter, D.R. (2008). Specification of Exponential-Family Random Graph Models: Terms and Computational Aspects. Journal of Statistical Software, 24(4), 1-24. (TNT proposal)

Hummel, R.M., Hunter, D.R., Handcock, M.S. (2012). Improving Simulation-Based Algorithms for Fitting ERGMs. Journal of Computational and Graphical Statistics, 21(4), 920-939. (MCMLE step length)

Geyer, C.J., Thompson, E.A. (1992). Constrained Monte Carlo Maximum Likelihood for Dependent Data. Journal of the Royal Statistical Society, Series B, 54(3), 657-699. (MCMLE)

nwergm is an independent, native reimplementation and is not affiliated with or endorsed by the Statnet project.

See also


Back to top

nwcommands is free to install and use, including for commercial research. See the GitHub repository for source, license, and issue tracking.

This site uses Just the Docs, a documentation theme for Jekyll.