AMME {netmediate} | R Documentation |
Function to estimate the average micro mediated effect (AMME).
Description
AMME
implements parametric and nonparametric estimation routines to estimate the
average mediated micro effect. It requires two models. The first is a generative network model (i.e., a model where the dyad, dyad-time period, or dyad-group is the unit of analysis) of the form f(A_{ij}|T_{ij},Z_{ij})
, where A
is a cross-sectional or longitudinal network or group of longitudinal or cross-sectional networks, T
is the possibly endogenous network selection process of interest and Z
is a matrix of possibly endogenous confounding selection mechanisms.
The second model is a cross-sectional or longitudinal macro model (i.e., a model where the unit of analysis is a node, subgraph, or network or a combination of nodes, subgraphs, and networks measured collected from multiple settings [such as distinct schools or organizations]) of the form g(Y_i|M_{i},X_{i},T_{i})
, where Y_i
is the outcome variable, M_i
is the mediating macro variable, X_i
is a matrix of control variables that possibly vary as a function of selection process T_{ij}
, and T_i
is the optional unit-level measure of T_{ij}
. The AMME is the change in Y_i
when T_{ij}
allowed to vary versus set to 0 because of an associated change in M_i
. The AMME is given by
AMME=\frac{1}{2n} y_i(T_i(t),M_i(T_{ij}),X_i(t))-y_i(T_i(t),M_i(0),X_i(t))
, where n
is the number of observations and t=0,T_{ij}
. AMME currently accepts the following micro models: glm
, glmer
, ergm
, btergm
, sienaFit
, rem.dyad
, and netlogit
objects. The following macro model objects are accepted: lm
, glm
, lmer
, glmer
, gam
, plm
, and lnam
objects. Pooled estimation for multiple network models is also implemented for ergm
and sienaFit
micro models. Both parametric and nonparametric estimation are available.
Usage
AMME(micro_model,
macro_model,
micro_process,
mediator,
macro_function,
link_id,
object_type=NULL,
controls=NULL,
control_functions=NULL,
interval=c(0,1),
nsim=500,
algorithm="parametric",
silent=FALSE,
full_output=FALSE,
SAOM_data=NULL,
SAOM_var=NULL,
time_interval=NULL,
covar_list=NULL,
edgelist=NULL,
net_logit_y=NULL,
net_logit_x=NULL,
group_id=NULL,
node_numbers=NULL)
Arguments
micro_model |
the micro-model. Currently accepts |
macro_model |
the macro model. Currently accepts |
micro_process |
a character string containing the name of the micro process of interest. The character string should exactly match the relevant coefficient name in |
mediator |
a character string containing the name of the mediating variable of interest. The character string should exactly match the relevant coefficient name in |
macro_function |
a |
link_id |
a required vector of IDs used to link the |
controls |
a vector of character strings listing the control variables in |
control_functions |
a list of functions used to calculate |
object_type |
A character string or vector of character strings that tells |
interval |
Tuning parameters to vary the strength of |
nsim |
The number of simulations or bootstrap samples to use during estimation. |
algorithm |
The estimation algorithm to be used. Currently accepts |
silent |
logical parameter. Whether to provide updates on the progress of the simulation or not. |
full_output |
logical parameter. If set to |
SAOM_data |
required when |
SAOM_var |
optional parameter when |
time_interval |
an optional parameter to be used when |
covar_list |
an optional list of sender/receiver covariates used in |
edgelist |
an optional three column edgelist providing the sender, receiver, and time of event occurrence when |
net_logit_y |
the dependent variable when |
net_logit_x |
the matrix of independent variables when |
group_id |
optional vector of group identifiers to use when |
node_numbers |
a numeric vector containing the number of nodes in each group_id when using |
Details
Estimates the AMME over the provided intervals. Standard errors and confidence intervals are based on the sampling distribution of simulated values, which are calculated either parametrically or nonparametrically according to algorithm
. Parametric estimation is typically faster, but cannot be used for nonparametric network models (e.g., quadratic assignment procedure).
macro_function
and control_functions
make up the core utilites of AMME
. macro_function
calculates the mediating variable of interest, while control_functions
calculates all control variables that vary as a function of micro_process
and potentially confound the effect of mediator
. When controls
are left NULL
, then AMME
estimates the AMME without accounting for confounding variables. Specifying controls
and control_functions
ensures that estimates of the AMME account for alternative pathways from micro_process
to the outcome variable in macro_model
. In cases where micro_process
is included as a predictor variable in macro_model
, this can be specified by including the netmediate
helper function identity_function
into control_functions
.
netmediate
currently supports functions calculated on igraph
and network
objects, which should be specified using the object_type
argument. These may be functions inherent to the statnet
and igraph
software package or they may be functions from other packages that accept network
/igraph
objects. The functions provided to macro_function
and control_functions
may also be user-defined functions that accept network
or igraph
objects as inputs and return a numeric value or vector of numeric values as output. It is also possible to over-ride the network
and igraph
object requirements within a user function. To do so, set the object_type
argument (or relevant element within the object_type
argument when object_type
is a list) to either network
or igraph
and then define a user-function that accepts a network
or igraph
object as its input, converts the object to the desired data structure, calculates the statistic of interest, and returns a numeric value or vector of numeric values. See examples below for an illustration.
By default, the AMME is calculated by averaging over the distribution of simulated values. If full_output
is set to TRUE
, the distribution of simualted statistics is returned. This may be useful when the median or mode of the simulated distribution is required or if the researcher wants to inspect the distributional shape of simulated values.
AMME
also supports pooled estimation for when multiple ergm
or sienaFit
objects are used as the micro_model
. To use pooled estimation, the model parameter should be specified as a list of ergm
or sienaFit
objects. If using sienaFit
, the SAOM_data
argument will also need to be specified as an ordered list with elements corresponding to entries in the list of sienaFit
objects. Similarly, the SAOM_var
parameter will need to be specified as a list of lists, where each entry in the list is, itself, a list containing all varCovar
and varDyadCovar
objects used to calculate macro statistics of interest. Note that SAOM_var
should not be provided if the macro statistic of interest is not a function of the variables contained in varCovar
and varDyadCovar
.
Value
If full_output=FALSE
, then a table is returned with the AMME, its standard error, confidence interval, and p-value.
If full_output=TRUE
, then a list is returned with the following three elements.
summary_dat |
is the table of summary output ucontaining the AMME, its standard error, confidence interval, and p-value. |
AMME_obs |
is vector of observations where each entry is the AMME for a single simulation trial. |
prop_explained_obs |
is vector containing the proportion explained values for each simulation trial. |
Author(s)
Duxbury, Scott W. Associate Professor, University of North Carolina–Chapel Hill, Department of Sociology.
References
Duxbury, Scott W. 2024. "Micro-macro Mediation Analysis in Social Networks." Sociological Methodology.
See Also
Examples
##############################
# Basic AMME specifications
#############################
####create ERGM generative model
library(statnet)
data("faux.mesa.high")
ergm_model<-ergm(faux.mesa.high~edges+
nodecov("Grade")+
nodefactor("Race")+
nodefactor("Sex")+
nodematch("Race")+
nodematch("Sex")+
absdiff("Grade"))
###create node-level data for second stage analysis with
node_level_data<-data.frame(grade=faux.mesa.high%v%"Grade",
race=faux.mesa.high%v%"Race",
sex=faux.mesa.high%v%"Sex",
degree=degree(faux.mesa.high))
node_level_data$senior<-0
node_level_data$senior[node_level_data$grade==max(node_level_data$grade)]<-1
node_level_data$v_id<-1:network.size(faux.mesa.high) #define ID for each observation
probit_model<-glm(senior~race+sex+degree,
data=node_level_data,
family=binomial(link="probit"))
###estimate the indirect effect of grade homophily on senior status acting through degree centrality
#in a model with no network control variables
AMME(micro_model=ergm_model,
macro_model=probit_model,
micro_process="absdiff.Grade",
mediator="degree",
macro_function=degree,
link_id=node_level_data$v_id, #specify vertex IDs
object_type="network",
interval=c(0,1),
nsim=50,
algorithm="parametric",
silent=FALSE)
#use nonparametric estimation for a generalized additive model
library(gam)
gam_model<-gam(senior~race+sex+s(degree),
data=node_level_data)
AMME(micro_model=ergm_model,
macro_model=gam_model,
micro_process="absdiff.Grade",
mediator="s(degree)",
macro_function=degree,
link_id=node_level_data$v_id,
object_type="network",
interval=c(0,1),
nsim=50,
algorithm="nonparametric",
silent=FALSE)
###estimate AMME with linear network autocorrelation model
lnam_model<-lnam(node_level_data$grade,
x=as.matrix(node_level_data[,4:5]),
W1=as.sociomatrix(faux.mesa.high))
AMME(micro_model=ergm_model,
macro_model=lnam_model,
micro_process="absdiff.Grade",
mediator="degree",
macro_function=degree,
link_id=node_level_data$v_id,
object_type="network",
interval=c(0,1),
nsim=50,
algorithm="parametric",
silent=FALSE)
############################
# Including controls
###########################
##single control
node_level_data<-data.frame(grade=faux.mesa.high%v%"Grade",
race=faux.mesa.high%v%"Race",
sex=faux.mesa.high%v%"Sex",
degree=degree(faux.mesa.high),
betweenness=betweenness(faux.mesa.high))
node_level_data$senior<-0
node_level_data$senior[node_level_data$grade==max(node_level_data$grade)]<-1
node_level_data$v_id<-1:network.size(faux.mesa.high) #define ID for each observation
probit_model<-glm(senior~race+sex+degree+betweenness,
data=node_level_data,
family=binomial(link="probit"))
AMME(micro_model=ergm_model,
macro_model=probit_model,
micro_process="absdiff.Grade",
mediator="degree",
macro_function=degree,
link_id=node_level_data$v_id, #specify vertex IDs
controls="betweenness", #should match model output exactly
control_functions=betweenness,
object_type="network",
interval=c(0,1),
nsim=50,
algorithm="parametric",
silent=FALSE)
##multiple controls
##include an AR 1 parameter to make it a nonlinear network autocorrelation model
node_level_data$AR1<-as.sociomatrix(faux.mesa.high)%*%node_level_data$senior
probit_model<-glm(senior~race+sex+degree+betweenness+AR1,
data=node_level_data,
family=binomial(link="probit"))
#specify user function
ar_function<-function(x){
return(as.sociomatrix(x)%*%node_level_data$senior)
}
AMME(micro_model=ergm_model,
macro_model=probit_model,
micro_process="absdiff.Grade",
mediator="degree",
macro_function=degree,
link_id=node_level_data$v_id,
controls=c("betweenness","AR1"), #should match model output exactly
control_functions=list(betweenness,ar_function), #provide functions as a list
object_type="network",
interval=c(0,1),
nsim=50,
algorithm="parametric",
silent=FALSE)
##using identity_function when micro_process has a direct effect on y
#to use identity_function, the control and micro_process need to have the same
#name and the macro control variable has to be numeric
node_level_data$Sex<-as.numeric(as.factor(node_level_data$sex))
logit_model<-glm(senior~race+Sex+degree+betweenness+AR1,
data=node_level_data,
family=binomial)
AMME(micro_model=ergm_model,
macro_model=logit_model,
micro_process="nodefactor.Sex.M",
mediator="degree",
macro_function=degree,
link_id=node_level_data$v_id,
controls=c("betweenness","AR1","Sex"), #should match model output exactly
control_functions=list(betweenness,ar_function,identity_function),
object_type="network",
interval=c(0,1),
nsim=50,
algorithm="parametric",
silent=FALSE)
################################
# More complex data structures
###############################
###############################
# AMME with longitudinal data
##############################
#bootstrap TERGM and panel data model
library(btergm)
library(plm)
data(alliances)
ally_data<-list(LSP[[1]],
LSP[[2]],
LSP[[3]])
#fit bootstrap TERGM with 200 replications
bt_model<-btergm(ally_data~edges+
gwesp(.7,fixed=T)+
mutual,R=200)
#create node data
ally_node_data<-data.frame(outdeg=c(rowSums(LSP[[1]]),rowSums(LSP[[2]]),rowSums(LSP[[3]])),
indeg=c(colSums(LSP[[1]]),colSums(LSP[[2]]),colSums(LSP[[3]])))
ally_node_data$v_id<-rep(rownames(LSP[[1]]),3) #create node IDS
ally_node_data$t_id<-c(rep(1, nrow(ally_data[[1]])), #create time IDS
rep(2, nrow(ally_data[[1]])),
rep(3, nrow(ally_data[[1]])))
ally_node_data$link_id<-paste(ally_node_data$v_id,ally_node_data$t_id)#create node-panel identifiers
ally_node_data$v_id<-as.factor(as.character(ally_node_data$v_id))
#estimate a linear model with node fixed effects
lm_model<- lm(outdeg~indeg +v_id,
data = ally_node_data)
AMME(micro_model=bt_model,
macro_model=lm_model,
micro_process="gwesp.OTP.fixed.0.7",
mediator="indeg",
macro_function=function(x){degree(x,cmode="indegree")},
link_id=ally_node_data$link_id, #provide node-panel identifiers
object_type="network",
interval=c(0,1),
nsim=11,
algorithm="nonparametric",
silent=FALSE)
##include controls at different units of analysis
#include global transitivity statistic at each network panel
transitivity_list<-c(gtrans(as.network(LSP[[1]])),
gtrans(as.network(LSP[[2]])),
gtrans(as.network(LSP[[3]])))
ally_node_data$transitivity<-c(rep(transitivity_list[1],nrow(LSP[[1]])),
rep(transitivity_list[2],nrow(LSP[[2]])),
rep(transitivity_list[3],nrow(LSP[[3]])))
lm_model<- lm(outdeg~indeg+transitivity +v_id,
data = ally_node_data)
AMME(micro_model=bt_model,
macro_model=lm_model,
micro_process="gwesp.OTP.fixed.0.7",
mediator="indeg",
macro_function=function(x){degree(x,cmode="indegree")},
link_id=list(ally_node_data$link_id,ally_node_data$t_id),#list of IDs for nodes and time
controls="transitivity",
control_functions = gtrans,
object_type="network",
interval=c(0,1),
nsim=11,
algorithm="nonparametric",
silent=FALSE)
#SAOM and panel data model with PLM package
library(RSiena)
#specify 3 wave network panel data as DV
network_list<-array(c(s501,s502,s503),dim = c(50,50,3))
Network<-sienaDependent(network_list)
Smoking<-varCovar(s50s)
Alcohol<-varCovar(s50a)
SAOM.Data<-sienaDataCreate(Network=Network,Smoking,Alcohol)
#specify
SAOM.terms<-getEffects(SAOM.Data)
SAOM.terms<-includeEffects(SAOM.terms,egoX,altX,sameX,interaction1="Alcohol")
SAOM.terms<-includeEffects(SAOM.terms,egoX,altX,sameX,interaction1="Smoking")
SAOM.terms<-includeEffects(SAOM.terms,transTies,inPop)
create.model<-sienaAlgorithmCreate(projname="netmediate",
nsub=5,
n3=2000)
##estimate the SAOM
SAOM_model<-siena07(create.model,
data=SAOM.Data,
effects=SAOM.terms,
verbose=TRUE)
##create node-level data
node_level_data<-data.frame(smoking=s50s[,1], #smoking behavior for DV
alcohol=s50a[,1],
v_id=rownames(s501), #unique node IDS
wave="Wave 1", #unique time IDS
outdegree=rowSums(s501),
indegree=colSums(s501),
AR1=s501%*%s50s[,1], #assign network autocorrelation
gcc=gtrans(as.network(s501)))
node_level_data<-rbind(node_level_data,data.frame(smoking=s50s[,2],
alcohol=s50a[,2],
v_id=rownames(s502),
wave="Wave 2",
outdegree=rowSums(s502),
indegree=colSums(s502),
AR1=s502%*%s50s[,2],
gcc=gtrans(as.network(s502))))
node_level_data<-rbind(node_level_data,data.frame(smoking=s50s[,3],
alcohol=s50a[,3],
v_id=rownames(s503),
wave="Wave 3",
outdegree=rowSums(s503),
indegree=colSums(s503),
AR1=s503%*%s50s[,3],
gcc=gtrans(as.network(s503))))
##create unique identifiers for node-panel
node_level_data$unique_ids<-paste(node_level_data$v_id,node_level_data$wave)
##estimate one-way fixed effects model with PLM
library(plm)
FE_model<-plm(smoking~alcohol+outdegree+indegree+AR1+gcc,
data=node_level_data,
index=c("v_id","wave"))
##create AR function to provide to AMME
ar_function<-function(x){return(as.sociomatrix(x)%*%(x%v%"Smoking"))}
AMME(micro_model=SAOM_model,
macro_model=FE_model,
micro_process="reciprocity",
mediator="indegree",
macro_function=function(x){degree(x,cmode="indegree")},
link_id=list(node_level_data$unique_id,node_level_data$unique_id,
node_level_data$unique_id,node_level_data$wave),
object_type="network",
controls=c("outdegree","AR1","gcc"),
control_functions=list(function(x){degree(x,cmode="outdegree")},ar_function,gtrans),
interval=c(0,.1),
nsim=500,
algorithm="parametric",
silent=FALSE,
SAOM_data = SAOM.Data,
SAOM_var=list(Smoking=Smoking,Alcohol=Alcohol)) #provide var_list
################################
# AMME with pooled ERGM and SAOM
################################
#pooled ERGM
#fit two ERGMs to two networks
data("faux.mesa.high")
model1<-ergm(faux.mesa.high~edges+
nodecov("Grade")+
nodefactor("Race")+
nodefactor("Sex")+
nodematch("Race")+
nodematch("Sex")+
absdiff("Grade"))
data("faux.magnolia.high")
model2<-ergm(faux.magnolia.high~edges+
nodecov("Grade")+
nodefactor("Race")+
nodefactor("Sex")+
nodematch("Race")+
nodematch("Sex")+
absdiff("Grade"))
#create node level data
node_level_data<-data.frame(grade=faux.mesa.high%v%"Grade",
sex=faux.mesa.high%v%"Sex",
degree=degree(faux.mesa.high),
betweenness=betweenness(faux.mesa.high),
gcc=gtrans(faux.mesa.high),
net_id="Mesa")
node_level_data$senior<-0
node_level_data$senior[node_level_data$grade==max(node_level_data$grade)]<-1
node_level_data$v_id<-1:network.size(faux.mesa.high)
node_level_data2<-data.frame(grade=faux.magnolia.high%v%"Grade",
sex=faux.magnolia.high%v%"Sex",
degree=degree(faux.magnolia.high),
betweenness=betweenness(faux.magnolia.high),
gcc=gtrans(faux.magnolia.high),
net_id="Magnolia")
node_level_data2$senior<-0
node_level_data2$senior[node_level_data$grade==max(node_level_data2$grade)]<-1
node_level_data2$v_id<-206:(network.size(faux.magnolia.high)+205)
node_level_data<-rbind(node_level_data,node_level_data2)
#estimate glm macro model with an AR 1 process
probit_model<-glm(senior~sex+degree+betweenness+gcc,
data=node_level_data,
family=binomial(link="probit"))
AMME(micro_model=list(model1,model2),
macro_model=probit_model,
micro_process="nodematch.Sex",
mediator="degree",
macro_function=degree,
link_id=list(node_level_data$v_id,node_level_data$v_id,node_level_data$net_id),
object_type="network",
controls=c("betweenness","gcc"),
control_functions=list(betweenness,gtrans),
interval=c(0,1),
nsim=50,
algorithm="parametric",
silent=FALSE)
##pooled SAOM with control functions using time varying covariates
library(RSiena)
#specify 3 wave network panel data as DV
network_list<-array(c(s501,s502,s503),dim = c(50,50,3))
Network<-sienaDependent(network_list)
Smoking<-varCovar(s50s)
Alcohol<-varCovar(s50a)
SAOM.Data<-sienaDataCreate(Network=Network,Smoking,Alcohol)
#specify
SAOM.terms<-getEffects(SAOM.Data)
SAOM.terms<-includeEffects(SAOM.terms,egoX,altX,sameX,interaction1="Alcohol")
SAOM.terms<-includeEffects(SAOM.terms,egoX,altX,sameX,interaction1="Smoking")
SAOM.terms<-includeEffects(SAOM.terms,transTies,inPop)
create.model<-sienaAlgorithmCreate(projname="netmediate",
nsub=5,
n3=2000)
##estimate the SAOM
SAOM_model<-siena07(create.model,
data=SAOM.Data,
effects=SAOM.terms,
verbose=TRUE)
##create node-level data
node_level_data<-data.frame(smoking=s50s[,1], #smoking behavior for DV
alcohol=s50a[,1],
v_id=rownames(s501), #unique node IDS
wave="Wave 1", #unique time IDS
outdegree=rowSums(s501),
indegree=colSums(s501),
AR1=s501%*%s50s[,1], #assign network autocorrelation
gcc=gtrans(as.network(s501)))
node_level_data<-rbind(node_level_data,data.frame(smoking=s50s[,2],
alcohol=s50a[,2],
v_id=rownames(s502),
wave="Wave 2",
outdegree=rowSums(s502),
indegree=colSums(s502),
AR1=s502%*%s50s[,2],
gcc=gtrans(as.network(s502))))
node_level_data<-rbind(node_level_data,data.frame(smoking=s50s[,3],
alcohol=s50a[,3],
v_id=rownames(s503),
wave="Wave 3",
outdegree=rowSums(s503),
indegree=colSums(s503),
AR1=s503%*%s50s[,3],
gcc=gtrans(as.network(s503))))
#recycle the same model for illustrative purposes
node_level_data$net_ID<-"Model 1"
node_level_data<-rbind(node_level_data,node_level_data)
node_level_data$net_ID[151:300]<-"Model 2"
##create unique identifiers for node-panel
#ID for node-panel-model
node_level_data$unique_id<-paste(node_level_data$v_id,node_level_data$wave,node_level_data$net_ID)
#ID for panel-model
node_level_data$unique_waves<-paste(node_level_data$wave,node_level_data$net_ID)
#estimate a linear network autocorrelation model with node fixed effects
FE_model<-lm(smoking~alcohol+outdegree+indegree+AR1+gcc+v_id,
data=node_level_data)
##create user function calculate AR1 process on time varying node attributes
ar_function<-function(x){return(as.sociomatrix(x)%*%(x%v%"Smoking"))}
##estimate AMME
AMME(micro_model=list(SAOM_model,SAOM_model), #provide list of sienaFit objects
macro_model=FE_model,
micro_process="reciprocity",
mediator="indegree",
macro_function=function(x){degree(x,cmode="indegree")},
link_id=list(node_level_data$unique_id,node_level_data$unique_id,
node_level_data$unique_id,node_level_data$unique_waves),
object_type="network",
controls=c("outdegree","AR1","gcc"),
control_functions=list(function(x){degree(x,cmode="outdegree")},ar_function,gtrans),
interval=c(0,.1),
nsim=100, #parametric estimation requires more simulations than coefficients
algorithm="parametric",
silent=FALSE,
SAOM_data = list(SAOM.Data,SAOM.Data), #list of siena objects
SAOM_var=list(list(Smoking=Smoking,Alcohol=Alcohol),#provide var_list
list(Smoking=Smoking,Alcohol=Alcohol)))
#################################
# AMME with nested data
################################
####create dyad-level data
library(lme4)
library(btergm)
##use small data to simplify estimation
glm_dat<-edgeprob(model1)
glm_dat$net_id<-"mesa"
glm_dat2<-edgeprob(model2)
glm_dat2$net_id<-"magnolia"
glm_dat<-rbind(glm_dat,glm_dat2[,-c(4)])
##estimate micro model as glm for btoh networks using pooled ERGM data
net_glm<-glm(tie~nodecov.Grade+
nodefactor.Race.Hisp+
nodefactor.Race.NatAm+
nodefactor.Race.Other+
nodefactor.Sex.M+
nodematch.Race+
nodematch.Sex+
absdiff.Grade,
data=glm_dat)
#create macro data
node_level_data<-data.frame(grade=faux.mesa.high%v%"Grade",
sex=faux.mesa.high%v%"Sex",
degree=degree(faux.mesa.high),
betweenness=betweenness(faux.mesa.high),
gcc=gtrans(faux.mesa.high),
net_id="Mesa")
node_level_data$senior<-0
node_level_data$senior[node_level_data$grade==max(node_level_data$grade)]<-1
node_level_data$v_id<-1:network.size(faux.mesa.high)
node_level_data2<-data.frame(grade=faux.magnolia.high%v%"Grade",
sex=faux.magnolia.high%v%"Sex",
degree=degree(faux.magnolia.high),
betweenness=betweenness(faux.magnolia.high),
gcc=gtrans(faux.magnolia.high),
net_id="Magnolia")
node_level_data2$senior<-0
node_level_data2$senior[node_level_data$grade==max(node_level_data2$grade)]<-1
node_level_data2$v_id<-206:(network.size(faux.magnolia.high)+205)
node_level_data<-rbind(node_level_data,node_level_data2)
#estimate glm macro model
probit_model<-glm(senior~sex+degree+betweenness+gcc,
data=node_level_data,
family=binomial(link="probit"))
AMME(micro_model=net_glm,
macro_model=probit_model,
micro_process="nodematch.Sex",
mediator="degree",
macro_function=degree,
link_id=list(node_level_data$v_id,node_level_data$v_id,node_level_data$net_id),
object_type="network",
controls=c("betweenness","gcc"),
control_functions=list(betweenness,gtrans),
interval=c(0,1),
nsim=50,
algorithm="parametric",
silent=FALSE,
group_id=glm_dat$net_id,
node_numbers = c(network.size(faux.mesa.high),
network.size(faux.magnolia.high)))
###using glmer for micro model
net_glmer<-glmer(tie~nodecov.Grade+
nodefactor.Race.Hisp+
nodefactor.Race.NatAm+
nodefactor.Race.Other+
nodefactor.Sex.M+
nodematch.Race+
nodematch.Sex+
absdiff.Grade+
(1|net_id),
data=glm_dat)
probit_glmer<-glm(senior~sex+degree+betweenness+gcc,
data=node_level_data,
family=binomial(link="probit"))
AMME(micro_model=net_glm,
macro_model=probit_glmer,
micro_process="nodematch.Sex",
mediator="degree",
macro_function=degree,
link_id=list(node_level_data$v_id,node_level_data$v_id,node_level_data$net_id),
object_type="network",
controls=c("betweenness","gcc"),
control_functions=list(betweenness,gtrans),
interval=c(0,1),
nsim=50,
algorithm="parametric",
silent=FALSE,
group_id=glm_dat$net_id,
node_numbers = c(network.size(faux.mesa.high),
network.size(faux.magnolia.high)))