diff --git a/.Rbuildignore b/.Rbuildignore index f3083d3..13f481a 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -6,6 +6,8 @@ ^\.github$ ^\.git$ ^checkEffects.R$ +^checkTheEffects.R$ +^checkEffects*.out$ ^ONEWS$ ^ONEWS_gh$ ^README.md$ diff --git a/.gitignore b/.gitignore index f51949c..f8d0ae5 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,8 @@ inst/doc autom4te.cache config.log config.status +checkTheEffects.R +checkEffects*.out docs/* !docs/manual/ docs/manual/Older/ diff --git a/DESCRIPTION b/DESCRIPTION index 46694dd..f295a2b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,8 +2,8 @@ Encoding: UTF-8 Package: RSiena Type: Package Title: Siena - Simulation Investigation for Empirical Network Analysis -Version: 1.6.8 -Date: 2026-06-06 +Version: 1.6.9 +Date: 2026-06-10 Authors@R: c(person("Tom A.B.", "Snijders", role = c("aut", "ctb"), comment = c(ORCID = "0000-0003-3157-4157")), person("Ruth M.", "Ripley", role = "aut"), person("Krists", "Boitmanis", role = c( "aut","ctb")), diff --git a/NEWS.md b/NEWS.md index 3cb6bb4..3f4a687 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,19 @@ +2026-06-10 + +# RSiena 1.6.9 + +## Changes in RSiena: +### Functionality + * `print.sienaGroup` now also specifies the node sets for covariates + and restricts printed line lengths to 64. + * Use of `r` in `estimate_onestep` effectuated. + * `checkEffects.R` corrected so that it will run without errors + and can be used for batch checking (will take a long time). +### Bug correction + * `make_specification` corrected for a continuous dependent behavior variable + and for two dependent networks and varying actor covariates (`effects.r`). + * Use of `prevAns` with one-step estimator corrected (`initializeFRAN.r`). + 2026-06-06 # RSiena 1.6.8 @@ -7,7 +23,7 @@ * Selection of effects for combinations of two dependent networks and an actor covariate improved, which leads to including more effects for combinations where one of the dependent networks - is bipartite. + is bipartite (`effects.r`, `effectsDocumentation.r`). ### Functionality * New function `estimate_onestep`. * Option `onestep` for `update_theta.sienaEffects` changed. diff --git a/R/effects.r b/R/effects.r index 9ffafcc..8d9eab7 100644 --- a/R/effects.r +++ b/R/effects.r @@ -421,8 +421,7 @@ getEffects <- function(x, nintn = 10, behNintn=4, getDocumentation=FALSE, onePer } for (k in seq(along=xx$depvars)) { - if ((types[k] %in% c('behavior', 'continuous')) && - (attr(xx$depvars[[k]], 'nodeSet') == nodeSet)) + if (types[k] %in% c('behavior', 'continuous')) { objEffects <- rbind(objEffects, @@ -1214,7 +1213,7 @@ getEffects <- function(x, nintn = 10, behNintn=4, getDocumentation=FALSE, onePer covarname=names(xx$vCovars)[k], nodeSets, # this is attr(depvar, 'nodeSet') attr(xx$depvars[[j]], 'nodeSet'), - attr(xx$cCovars[[k]], 'nodeSet'), + attr(xx$vCovars[[k]], 'nodeSet'), name=varname)) } for (k in seq(along = xx$dycCovars)) @@ -1247,15 +1246,16 @@ getEffects <- function(x, nintn = 10, behNintn=4, getDocumentation=FALSE, onePer } for (k in seq(along=xx$depvars)) { - if (types[k] %in% c('behavior', 'continuous') && - attr(xx$depvars[[k]], 'nodeSet') == nodeSets[1]) + if (types[k] %in% c('behavior', 'continuous')) { objEffects <- rbind(objEffects, - createEffects("covarABipNetObjective", otherName, - names(xx$depvars)[k], name=varname, - groupName=groupName, group=group, - netType=netType)) + covarNetNetEff(otherName, + covarname=names(xx$depvars)[k], + nodeSets, # this is attr(depvar, 'nodeSet') + attr(xx$depvars[[j]], 'nodeSet'), + attr(xx$depvars[[k]], 'nodeSet'), + name=varname)) } } } diff --git a/R/initializeFRAN.r b/R/initializeFRAN.r index 6999897..b8bd867 100644 --- a/R/initializeFRAN.r +++ b/R/initializeFRAN.r @@ -278,7 +278,7 @@ initializeFRAN <- function(z, x, data, effects, prevAns=NULL, initC, if (x$useOneStep) { keepStill <- which(prevAns$fixed) - if (length(keepStill == 0)) + if (length(keepStill) == 0) { keepStill <- 0 } @@ -2153,7 +2153,7 @@ update_theta.sienaEffects <- function(x, prevAns, varName=NULL, eff <- updateTheta(x, prevAns=prevAns, varName=varName) if (onestep) { - est_onestep <- estimate_onestep(prevAns, fixed=keepUnchanged) + est_onestep <- estimate_onestep(prevAns, fixed=keepUnchanged, r=r) effsF <- prevAns$requestedEffects requested <- which(names(prevAns$requestedEffects)=="requested") effsF$initialValue <- est_onestep diff --git a/R/sienaprint.r b/R/sienaprint.r index 74adaee..c89bf1b 100644 --- a/R/sienaprint.r +++ b/R/sienaprint.r @@ -13,6 +13,39 @@ ## * even if these main effects were not requested. ## * ## ****************************************************************************/ + +##@printWithLineMax for print.siena; prints character strings +printWithLineMax <- function(heading, contents, contentkinds){ +# function to print contents with categories contentkinds +# with a heading; line length maximum 4 + 60 +# heading is a character string, +# contents and contentkinds are characters strings of the same length + if (length(contents) != length(contentkinds)) + { + stop("Error in printWithLineMax: contents and contentkinds have different length") + } + vsets <- unique(contentkinds) + for (vk in vsets) + { + cat(heading, "<", vk, "> : \n") + contentk <- contents[contentkinds==vk] + cumlength <- 0 + cat(" ") + for (k in seq_along(contentk)) + { + cumlength <- cumlength + nchar(contentk[k]) + if (cumlength > 60) + { + cat("\n ") + cumlength <- 0 + } + cat(contentk[k]) + if (k < length(contentk)){cat(", ")} + } + cat("\n") + } + cat("\n") +} ##@print.sienadata Methods print.sienadata <- function(x, ...) { @@ -51,38 +84,6 @@ print.sienadata <- function(x, ...) } } } - ##@printWithLineMax internal print.siena; prints character strings - printWithLineMax <- function(heading, contents, contentkinds){ - # function to print contents with categories contentkinds - # with a heading; line length maximum 4 + 60 - # heading is a character string, - # contents and contentkinds are characters strings of the same length - if (length(contents) != length(contentkinds)) - { - stop("Error in printWithLineMax: contents and contentkinds have different length") - } - vsets <- unique(contentkinds) - for (vk in vsets) - { - cat(heading, "<", vk, "> : \n") - contentk <- contents[contentkinds==vk] - cumlength <- 0 - cat(" ") - for (k in seq_along(contentk)) - { - cumlength <- cumlength + nchar(contentk[k]) - if (cumlength > 60) - { - cat("\n ") - cumlength <- 0 - } - cat(contentk[k]) - if (k < length(contentk)){cat(", ")} - } - cat("\n") - } - cat("\n") - } # begin main method siena.print proper if ((!inherits(x, "sienadata")) & (!inherits(x, "siena"))) { @@ -243,16 +244,20 @@ print.sienaGroup <- function(x, ...) cat('Dependent variables: \n') cat(paste(att$netnames, ":", att$types,'\n')) cat('Total number of groups:', length(x),'\n') - cat('Total number of periods:', att$observations,'\n') + cat('Total number of periods:', att$observations,'\n') if (length(x[[1]]$vCovars) > 0) { - cat('Changing covariates: ', - paste(names(x[[1]]$vCovars), collapse = ", "), "\n") - } + vnodesets <- sapply(x[[1]]$vCovars, function(v){attr(v,"nodeSet")}) + printWithLineMax("Changing covariates for node set", names(x[[1]]$vCovars), vnodesets) + } if (length(x[[1]]$dyvCovars) > 0) { - cat('Changing dyadic covariates: ', - paste(names(x[[1]]$dyvCovars), collapse=", "), "\n") + kindNodeSets <- rep("", length(x[[1]]$dyvCovars)) + for (k in seq_along(x[[1]]$dyvCovars)) + { + kindNodeSets[k] <- paste(attr(x[[1]]$dyvCovars[[k]],"nodeSet"), collapse=", ") + } + printWithLineMax("Changing dyadic covariates for node sets", names(x[[1]]$dyvCovars), kindNodeSets) } cat("\n") invisible(x) diff --git a/checkEffects.R b/checkEffects.R index 10d88c9..2b9469a 100644 --- a/checkEffects.R +++ b/checkEffects.R @@ -305,7 +305,7 @@ mydata <- sienaDataCreate(mynet, mybeh) mymodel <- getEffects(mydata) mymodel <- includeEffects(mymodel,avSim,name='mybeh',interaction1='mynet') mymodel -mycontrols <- sienaAlgorithmCreate(projname=NULL) +mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=54321) (ans <- siena07(mycontrols, data=mydata, effects=mymodel)) ans$targets # linear shape and quadratic shape @@ -421,7 +421,7 @@ mynet <- sienaDependent(array(c(s502, s503), dim=c(50, 50, 2))) mybeh <- sienaDependent(s50a[,2:3], type="behavior") mydata <- sienaDataCreate(mynet, mybeh) mymodel <- getEffects(mydata) -mycontrols <- sienaAlgorithmCreate(projname=NULL) +mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=123) # for avAttHigher effect: mymodel <- getEffects(mydata) mymodel <- includeEffects(mymodel,avAttHigher,name='mybeh',interaction1='mynet') @@ -477,7 +477,7 @@ mymodel <- includeEffects(mymodel, crprodInActIntn, name='mynet2', interaction1='mynet1') mymodel -mycontrols <- sienaAlgorithmCreate(projname=NULL) +mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=123) # for crprodInActIntn effect (parameter = 2): (ans <- siena07(mycontrols, data=mydata, effects=mymodel)) ans$targets @@ -505,7 +505,7 @@ mydata <- sienaDataCreate(mynet, mybeh, mycov) mymodel <- getEffects(mydata) (mymodel <- includeEffects(mymodel,RateX,type='rate', name='mybeh',interaction1='mycov')) -mycontrols <- sienaAlgorithmCreate(projname=NULL) +mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=123) (ans <- siena07(mycontrols, data=mydata, effects=mymodel)) ans$targets sum(abs(mybeh[,,1]-mybeh[,,2])) # OK rate @@ -1009,8 +1009,7 @@ n <- 50 intwostars2 <- (s502) %*% t(s502) diag(intwostars2) <- 0 (cc <- (n/(2*(n-1)))*mean(intwostars1 + intwostars2)) -sum((intwostars1-cc) * intwostars3) # 122.3959 -OK +sum((intwostars1-cc) * intwostars3) # 122.3959 OK ### mymodel <- getEffects(mydata) @@ -1056,7 +1055,8 @@ mymodel <- getEffects(mydata) mymodel <- setEffect(mymodel,avInAltW, name = 'beh', interaction1 = 'mynet', interaction2 = 'dcov', parameter = 2) -(ans1 <- siena07(mycontrols, data = mydata, effects = mymodel)) +(ans1 <- siena07(mycontrols, data = mydata, effects = mymodel, + thetaBound=100)) ans1$targets avinwalt <- divi( ((dcova - mdc)*t(s501)) %*% (beh[,,2] - mbh), rowSums(t(s501)*(dcova-mdc))) @@ -1599,7 +1599,7 @@ diag(mat) <- 0 sum((rowSums(s502 * mat))*sqrt(rowSums(s502 * mat))) # 80.0443 OK mymodel <- getEffects(mydata) -mymodel <- includeEffects(mymodel, diffXOutAct, interaction1="covsets", parameter=1) +mymodel <- setEffect(mymodel, diffXOutAct, interaction1="covsets", parameter=1) (mymodel <- includeEffects(mymodel, outAct)) (ans <- siena07(mycontrols, data=mydata, effects=mymodel)) ans$targets # 116 70 350 138 @@ -2849,7 +2849,7 @@ sum(s503r * s501) # 31 OK # contemp: sum(s503r * s502) # 36, different which is good -myeff2 <- includeGMoMStatistics(myeff, crprod_gmm, name='mynet2', interaction1='mynet1') +myeff2 <- includeGMoMStatistics(myeff, crprod_gmm, depvar='mynet2', covar1='mynet1') myeff2 algorithm2 <- sienaAlgorithmCreate(nsub=2, n3=1000, gmm=TRUE, seed=4321) @@ -2864,7 +2864,7 @@ ans5$targets # OK myeff6 <- setEffect(myeff, from, name='mynet2', interaction1='mynet1') (ans6 <- siena07(mycontrols, data=mydata, effects=myeff6)) -myeff7 <- includeGMoMStatistics(myeff6, from_gmm, name='mynet2', interaction1='mynet1') +myeff7 <- includeGMoMStatistics(myeff6, from_gmm, depvar='mynet2', covar1='mynet1') (ans7 <- siena07(algorithm2, data=mydata, effects=myeff7)) (ans7 <- siena07(algorithm4, data=mydata, effects=myeff7, prevAns=ans7)) ans7$targets @@ -2874,7 +2874,7 @@ sum(s503r * (s502 %*% t(s502))) # 51 OK myeff8 <- setEffect(myeff, to, name='mynet2', interaction1='mynet1') (ans8 <- siena07(mycontrols, data=mydata, effects=myeff8)) -myeff9 <- includeGMoMStatistics(myeff8, to_gmm, name='mynet2', interaction1='mynet1') +myeff9 <- includeGMoMStatistics(myeff8, to_gmm, depvar='mynet2', covar1='mynet1') (ans9 <- siena07(algorithm2, data=mydata, effects=myeff9)) (ans9 <- siena07(algorithm4, data=mydata, effects=myeff9, prevAns=ans9)) ans9$targets @@ -3261,7 +3261,7 @@ mymodel <- getEffects(mydata) mymodel <- setEffect(mymodel, outAct) mymodel <- setEffect(mymodel, outActMore_ego, parameter=3) mymodel -mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=1234) +mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=51234) (ans <- siena07(mycontrols, data=mydata, effects=mymodel)) ans$targets sum(rowSums(s502)^2) # OK @@ -3280,7 +3280,7 @@ mymodel <- getEffects(mydata) mymodel <- setEffect(mymodel, outAct) mymodel <- setEffect(mymodel, outMore_ego, parameter=3) mymodel -(ans <- siena07(mycontrols, data=mydata, effects=mymodel)) +(ans <- siena07(mycontrols, data=mydata, effects=mymodel, thetaBound=1000)) ans$targets sum(rowSums(s502)* (rowSums(s502))) # 350 OK sum(rowSums(s502)*(rowSums(s502)> 3)) # 35 OK @@ -3325,12 +3325,21 @@ thedata <- sienaDataCreate( beh = sienaDependent(s50a[,1:2], type='behavior') ) +gm <- mean(s50a[,1:2]) + +avAlt <- function(n, b){ +# calculates peers' average behavior; +# n = adjacency matrix senders (rows) by receivers (cols) +# b = behavior vector + n %*% b / rowSums(n) +} + # specify w/ contemporaneously centered effects alongside grand-mean centered ones: model <- getEffects(thedata) model <- includeEffects(model, quad_cc, name='beh') model <- includeEffects(model, avAlt, avAlt_cc, name='beh', interaction1='net') -modelsum((s50a[,2]-gm) * (avAlt(s501, s50a[,2])-gm), na.rm=TRUE) # is okay - <- includeEffects(model, quad, quad_cc, name='beh') +model +sum((s50a[,2]-gm) * (avAlt(s501, s50a[,2])-gm), na.rm=TRUE) # is okay model <- includeEffects(model, egoX, egoX_cc, altX, altX_cc, name='net', interaction1='beh') # fix grand-mean centered old veriants to avoid collinearity in estimation: model <- setEffect(model, avAlt, fix=TRUE, test=TRUE, @@ -3352,12 +3361,6 @@ thecontrols <- sienaAlgorithmCreate(seed=1234) cc <- mean(s50a[,2]) # contemporaneous mean at end of period gm <- mean(s50a[,1:2]) # grand mean over both observations -avAlt <- function(n, b){ -# calculates peers' average behavior; -# n = adjacency matrix senders (rows) by receivers (cols) -# b = behavior vector - n %*% b / rowSums(n) -} # calculate targets avAlt and avAlt_cc manually: sum((s50a[,2]-gm) * (avAlt(s501, s50a[,2])-gm), na.rm=TRUE) # 33.5746 ok @@ -3378,7 +3381,7 @@ mymodel <- getEffects(mydata) p <- 1 mymodel <- setEffect(mymodel,avGroup, name='mybeh', parameter=p) mymodel -mycontrols <- sienaAlgorithmCreate(projname=NULL) +mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=123) (ans <- siena07(mycontrols, data=mydata, effects=mymodel)) ans$targets @@ -3404,7 +3407,7 @@ mymodel <- getEffects(mydata) p <- 1 mymodel <- setEffect(mymodel,totGroup, name='mybeh', parameter=p) mymodel -mycontrols <- sienaAlgorithmCreate(projname=NULL) +mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=123) (ans <- siena07(mycontrols, data=mydata, effects=mymodel)) ans$targets @@ -3472,7 +3475,7 @@ p <- 1 mymodel <- setEffect(mymodel,indegAvGroup, name='mybeh', interaction1='mynet', parameter=p) mymodel -mycontrols <- sienaAlgorithmCreate(projname=NULL) +mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=123) (ans <- siena07(mycontrols, data=mydata, effects=mymodel, batch=TRUE, verbose=TRUE)) ans$targets (mbh <- mean(mybeh)) @@ -3499,7 +3502,7 @@ mymodel <- includeEffects (mymodel, linear, quad, name='mybeh', include=FALSE) mymodel <- setEffect(mymodel,indegAvGroup, name='mybeh', interaction1='mynet', parameter=p) mymodel -mycontrols <- sienaAlgorithmCreate(projname=NULL) +mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=123) (ans <- siena07(mycontrols, data=mydata, effects=mymodel, batch=TRUE, verbose=TRUE)) (ans <- siena07(mycontrols, data=mydata, effects=mymodel, batch=TRUE, verbose=TRUE, prevAns = ans, returnDeps=TRUE)) @@ -3522,7 +3525,7 @@ p <- 1 mymodel <- setEffect(mymodel,indegTotGroup, name='mybeh', interaction1='mynet', parameter=p) mymodel -mycontrols <- sienaAlgorithmCreate(projname=NULL) +mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=123) (ans <- siena07(mycontrols, data=mydata, effects=mymodel, batch=TRUE, verbose=TRUE)) ans$targets (mbh <- mean(mybeh)) @@ -3549,7 +3552,7 @@ mymodel <- includeEffects (mymodel, linear, quad, name='mybeh', include=FALSE) mymodel <- setEffect(mymodel,indegTotGroup, name='mybeh', interaction1='mynet', parameter=p) mymodel -mycontrols <- sienaAlgorithmCreate(projname=NULL) +mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=123) (ans <- siena07(mycontrols, data=mydata, effects=mymodel, batch=TRUE, verbose=TRUE)) (ans <- siena07(mycontrols, data=mydata, effects=mymodel, batch=TRUE, verbose=TRUE, prevAns = ans, returnDeps=TRUE)) @@ -4033,7 +4036,7 @@ mynet <- sienaDependent(array(c(s502, s503), dim=c(50, 50, 2))) mybeh <- sienaDependent(s50a[,2:3], type="behavior") mydata <- sienaDataCreate(mynet, mybeh) mymodel <- getEffects(mydata) -mycontrols <- sienaAlgorithmCreate(projname=NULL) +mycontrols <- sienaAlgorithmCreate(projname=NULL, seed=123) # popAlt mymodel <- includeEffects(mymodel, popAlt, name='mybeh', interaction1='mynet') diff --git a/docs/manual/RSiena_Manual.pdf b/docs/manual/RSiena_Manual.pdf index ad4473b..5638ce1 100644 Binary files a/docs/manual/RSiena_Manual.pdf and b/docs/manual/RSiena_Manual.pdf differ diff --git a/docs/manual/RSiena_Manual.tex b/docs/manual/RSiena_Manual.tex index e9105f1..b176633 100644 --- a/docs/manual/RSiena_Manual.tex +++ b/docs/manual/RSiena_Manual.tex @@ -216,7 +216,7 @@ and Viviana Amati. This manual is frequently updated, mostly only in a minor way. -This version was renewed for \RS version1.6.8. +This version was renewed for \RS version1.6.9. In version 1.6, the names of \RS functions have undergone important changes. This manual is for the new names. @@ -1187,7 +1187,7 @@ \subsection{Getting help with problems} of \rs. Details of the latest version available can be found at the `Downloads' page. The version is - identified by a version number (e.g., 1.6.8). + identified by a version number (e.g., 1.6.9). You can find the number of your current installed version by opening \R, and typing\\ \verb|packageVersion("RSiena")| \\ @@ -6616,6 +6616,21 @@ \subsection{Maximum Likelihood and Bayesian estimation} a few estimation runs. +\subsubsection{Treatment of missing data} + +For missing data in the dependent variables (not in the covariates!), +a different procedure is used than the one in the Methods of Moments +estimation procedure. +The missing data at the beginning of the wave are modeled as random +variables with a simple prior distribution, given by the +distribution of the non-missing entries for this wave. +(For Maximum Likelihood estimation, this is a Bayesian incursion +in an otherwise frequentist approach...) +The missing data at the end of the wave are modeled +as random variables with the distribution implied +by the Markov chain model with the estimated parameters. + + \iffalse \SI supplies three alternative MCMC algorithms for the Bayesian estimation of the objective function parameters: @@ -8884,13 +8899,27 @@ \subsection{Random coefficient multilevel Siena analysis} determined by parameter \texttt{mult} (`multiplication factor') in the call of \textsf{set\_algorithm\_saom} that created the algorithm object. \end{enumerate} - The function \textsf{multi\_siena} is time-consuming. When starting to use it, it is advisable + The function \textsf{multi\_siena} is time-consuming. When starting to use it, + it is advisable to start with low values of \texttt{nmain} to explore computing time. When the procedure seems to diverge, and for very small groups, it is advisable to use smaller values of the parameters \texttt{initgainGlobal} and \texttt{initgainGroupwise}; and perhaps \texttt{reductionFactor}. +\subsubsection{Treatment of missing data} + +For missing data in the dependent variables (not in the covariates!), +a different procedure is used than the one in the Methods of Moments +estimation procedure. +The missing data at the beginning of the wave are modeled as random +variables with a simple prior distribution, given by the +distribution of the non-missing entries for this wave. +The missing data at the end of the wave are modeled +as random variables with the distribution implied +by the Markov chain model with the estimated parameters. + + \subsubsection{Which data sets to use for multi\_siena} \label{S_sBData} @@ -8961,8 +8990,8 @@ \subsubsection{Model specification} The extra part of model specification for \textsf{multi\_siena}, compared to \textsf{siena}, is that it is required to specify which parameters are -randomly varying from group to group, and which are fixed across groups. -The specification of fixed vs.\ randomly varying +randomly varying from group to group, and which are constant across groups. +The specification of constant vs.\ randomly varying for the other parameters is done in the function \textsf{set\_effect}, by its parameter \texttt{random}. To be able to see which of the effects are specified in this way, @@ -8981,7 +9010,7 @@ \subsubsection{Model specification} The exception to the rate parameters being always randomly varying is that they may be fixed --- in which case all of them need to be fixed, and input parameter \\ -\texttt{priorRatesFromData} needs to be set to --2. +\texttt{priorRatesFromData} needs to be set to --1. \medskip There currently is little advice about which effects to specify @@ -8999,21 +9028,21 @@ \subsubsection{Model specification} varying for which the time heterogeneity is largest according to the groupwise results.) \item[\emph{misspecification:}] if it would be erroneously assumed - that the effect is fixed across groups, would this affect + that the effect is constant across groups, would this affect the parameter estimates of primary interest?\\ (About this we have little general knowledge; it can be tried out by running estimations for different specifications of this part of the model.) \item[\emph{convergence:}] specifying effects as random will influence convergence. Up to a point, randomly varying parameters - will have better convergence properties than fixed parameters; + will have better convergence properties than constant parameters; but if their number is too large, given the number of groups, convergence can deteriorate again. This may then lead to outliers in the posterior means, which can be diagnosed by function \sfn{plotPostMeansMDS}. \item[\emph{amount of information:}] which specification will use the information in the data most efficiently?\\ - (Here finally we do have a provisional answer. Assuming that an effect is fixed + (Here finally we do have a provisional answer. Assuming that an effect is constant across groups will give a smaller uncertainty ---posterior standard deviation, interpreted as standard error--- in the estimated parameter than assuming it varies randomly; @@ -9023,7 +9052,7 @@ \subsubsection{Model specification} there is no strong prior knowledge that they are variable across groups, and which are tested as a primary issue for answering the research question, from the point of view of statistical power - it is advisable to specify that they are fixed.) + it is advisable to specify that they are constant.) \end{description} @@ -9526,10 +9555,10 @@ \subsubsection{Interpreting results of multi\_siena} \medskip When comparing results for specifications that differ with respect -to specifying the effects as fixed or varying across groups, +to specifying the effects as constant or varying across groups, it will be noted that posterior standard deviations for the means are larger when specifying the effects as randomly varying, as compared -to specifying them as fixed. This is natural, and it is associated +to specifying them as constant. This is natural, and it is associated with a difference in interpretation. Specifying the effect as randomly varying implies that there also is an important step of generalization from the observed groups to the population @@ -17736,12 +17765,12 @@ \section{For programmers: Building, installing and checking the package} them to the repository. \item [Check] Checking is a process designed to ensure that packages are likely to work correctly when installed. Type -\verb|R CMD check RSiena_1.6.8.tar.gz|\\ +\verb|R CMD check RSiena_1.6.9.tar.gz|\\ (where the version number is adjusted to match the tar ball name.) \item[zip file] To make a zip file that can be used in Windows for `installing from a local zip file', and therefore is easy for distribution to others, type\\ -\verb|R CMD INSTALL --build RSiena_1.6.8.tar.gz| \\ +\verb|R CMD INSTALL --build RSiena_1.6.9.tar.gz| \\ (where again the version number is adjusted to match the tar ball name.) \end{description} @@ -18408,7 +18437,7 @@ \section{Appendix: Changes compared to earlier versions} \fi -\item 2026-06-06 GitHub, package version 1.6.8. +\item 2026-06-10 GitHub, package version 1.6.9. Changes in RSiena: \begin{itemize} @@ -18424,9 +18453,9 @@ \section{Appendix: Changes compared to earlier versions} \item New function \sfn{estimate\_onestep}. \item Option \texttt{onestep} for \sfn{update\_theta.sienaEffects} changed. \item Hidden option to use the one-step estimator with - \texttt{prevAns} in \sfn{siena}. - \item \sfn{print.sienadata} now specifies the node sets for covariates - and restricts printed line lengths to 64. + \texttt{prevAns} in \sfn{siena} (experimental). + \item \sfn{print.sienadata} and \sfn{print.sienaGroup} now specify + the node sets for covariates and restricts printed line lengths to 64. \item More informative error message in \sfn{make\_data\_rsiena} if the number of elements of the second node set for bipartite networks is not correct. \item In \sfn{transformScript}, the replacement for \sfn{descriptives.sienaGOF} @@ -18437,7 +18466,7 @@ \section{Appendix: Changes compared to earlier versions} \item Reorganization and clarification of \texttt{effectGroups} for combinations of two dependent networks and an actor covariate: these now are \texttt{covarNetNetObjective}, \\ - \texttt{covarANetNetObjective},\texttt{covarAWNetNetObjective},\\ + \texttt{covarANetNetObjective}, \texttt{covarAWNetNetObjective},\\ \texttt{covarADNetNetObjective}, \texttt{covarBNetNetObjective},\\ \texttt{covarBXNetNetObjective}. diff --git a/man/RSiena-package.Rd b/man/RSiena-package.Rd index 312466c..02fc600 100644 --- a/man/RSiena-package.Rd +++ b/man/RSiena-package.Rd @@ -52,8 +52,8 @@ Bug reports can be submitted at \tabular{ll}{ Package: \tab RSiena\cr Type: \tab Package\cr - Version: \tab 1.6.8\cr - Date: \tab 2026-06-06\cr + Version: \tab 1.6.9\cr + Date: \tab 2026-06-10\cr Depends: \tab R (>= 4.5.0)\cr Imports: \tab Matrix, lattice, parallel, MASS, methods, xtable\cr Suggests: \tab network, tools, codetools, tcltk\cr diff --git a/man/set_algorithm_saom.Rd b/man/set_algorithm_saom.Rd index 0acc87a..cf0d119 100644 --- a/man/set_algorithm_saom.Rd +++ b/man/set_algorithm_saom.Rd @@ -41,26 +41,27 @@ set_algorithm_saom(maxlike = FALSE, gmm = FALSE, cond = NA, condvarno = 0, condname = "", simOnly = FALSE, - targets = NULL, thetaValues = NULL, seed = NULL, + targets = NULL, thetaValues = NULL, + seed = NULL, n3 = 1000, nsub = 4, n2start = NULL, firstg = 0.2, reduceg = 0.5, truncation = 5, doubleAveraging = 0, diagonalize = 0.2*!maxlike, standardizeVar = (diagonalize<1), - dolby = TRUE, splitDepvars = 0, - useStdInits = FALSE, findiff = FALSE, + dolby = TRUE, splitDepvars = 0, + useStdInits = FALSE, findiff = FALSE, mult = 5, prML = 1, maximumPermutationLength = 40, minimumPermutationLength = 2, initialPermutationLength = 20, localML = FALSE) set_output_saom(outputName = NULL, lessMem = FALSE, - returnThetas = FALSE, + returnThetas = FALSE, returnChains = FALSE, returnDataFrame = FALSE, returnChangeContributions = FALSE) sienaAlgorithmCreate(fn, projname = "Siena", MaxDegree = NULL, - Offset = NULL, useStdInits = FALSE, + Offset = NULL, useStdInits = FALSE, n3 = 1000, nsub = 4, n2start = NULL, - dolby = TRUE, splitDepvars = 0, - maxlike = FALSE, gmm = FALSE, + dolby = TRUE, splitDepvars = 0, + maxlike = FALSE, gmm = FALSE, diagonalize = 0.2*!maxlike, condvarno = 0, condname = "", firstg = 0.2, reduceg = 0.5, cond = NA, findiff = FALSE, seed = NULL, @@ -71,10 +72,10 @@ sienaAlgorithmCreate(fn, projname = "Siena", MaxDegree = NULL, standardizeVar = (diagonalize<1), lessMem = FALSE, silent = FALSE) sienaModelCreate(fn, projname = "Siena", MaxDegree = NULL, - Offset = NULL, useStdInits = FALSE, + Offset = NULL, useStdInits = FALSE, n3 = 1000, nsub = 4, n2start = NULL, - dolby = TRUE, splitDepvars = 0, - maxlike = FALSE, gmm = FALSE, + dolby = TRUE, splitDepvars = 0, + maxlike = FALSE, gmm = FALSE, diagonalize = 0.2*!maxlike, condvarno = 0, condname = "", firstg = 0.2, reduceg = 0.5, cond = NA, findiff = FALSE, seed = NULL, @@ -135,9 +136,9 @@ sienaModelCreate(fn, projname = "Siena", MaxDegree = NULL, Method of Moments estimation.} \item{cond}{Boolean. Only relevant for Method of Moments simulation/estimation. - If TRUE, use conditional simulation; if FALSE, unconditional simulation. + If \code{TRUE}, use conditional simulation; if FALSE, unconditional simulation. If missing, decision is deferred until \code{\link{siena}}, - when it is set to TRUE if there is only one dependent variable, + when it is set to \code{TRUE} if there is only one dependent variable, FALSE otherwise.} \item{condvarno}{If \code{cond} (conditional simulation), the sequential number of the network @@ -145,7 +146,7 @@ sienaModelCreate(fn, projname = "Siena", MaxDegree = NULL, \item{condname}{If conditional, the name of the dependent variable on which to condition. Use one or other of \code{condname} or \code{condvarno} to specify the variable.} - \item{simOnly}{Logical: If TRUE, then the calculation of the covariance + \item{simOnly}{Logical: If \code{TRUE}, then the calculation of the covariance matrix and standard errors of the estimates at the end of Phase 3 of the estimation algorithm is skipped. This is suitable if nsub = 0 and \code{\link{siena}} @@ -192,19 +193,19 @@ sienaModelCreate(fn, projname = "Siena", MaxDegree = NULL, \item{standardizeVar}{Logical: whether to limit deviations used in Robbins-Monro updates to unit variances.} \item{dolby}{Boolean. Should there be noise reduction by regression - on augmented data score. In most cases dolby = TRUE yields better + on augmented data score. In most cases \code{dolby = TRUE} yields better convergence, but takes some extra computing time; - if convergence is problematic, however, dolby = FALSE may be tried. + if convergence is problematic, however, \code{dolby = FALSE} may be tried. Just use whatever works best.} - \item{splitDepvars}{Integer with possible values \code{-1, 0, +1}. + \item{splitDepvars}{Integer with possible values \code{-1, 0, +1}. If \code{-1}, obtain results as in versions prior to 1.3.6. If \code{+1}, Robbins-Monro updates for a given dependent - variable will not depend on deviations for other dependent variables. - See Details.} - \item{useStdInits}{Boolean. If TRUE, the initial values in the effects + variable will not depend on deviations for other dependent variables. + See Details.} + \item{useStdInits}{Boolean. If \code{TRUE}, the initial values in the effects object will be ignored and default values used instead. If FALSE, the initial values in the effects object will be used.} - \item{findiff}{ Boolean: If TRUE, estimate derivatives using finite + \item{findiff}{ Boolean: If \code{TRUE}, estimate derivatives using finite differences. If FALSE, use scores.} \item{mult}{Multiplication factor for maximum likelihood and Bayes. Number of steps per iteration is set to this multiple of the total distance @@ -227,7 +228,7 @@ sienaModelCreate(fn, projname = "Siena", MaxDegree = NULL, in steps in MLestimation.} \item{initialPermutationLength}{Initial length of permutation in steps in MLestimation.} - \item{localML}{Logical: If TRUE, and \code{maxlike}, then calculations + \item{localML}{Logical: If \code{TRUE}, and \code{maxlike}, then calculations are sped up for models with all local effects.} For \code{set_output_saom}: \item{outputName}{If \code{outputName = NULL} and the Siena data set @@ -268,11 +269,11 @@ sienaModelCreate(fn, projname = "Siena", MaxDegree = NULL, Robbins-Monro algorithm. Those not available as arguments can be changed manually when desired.\cr The matrix \code{D} transforming deviations from targets to updates - in the Robbins Monro steps are partially diagonalized + in the Robbins Monro steps are partially diagonalized if \code{diagonalize > 0}; and its between-dependent variable blocks are put to \code{0} if \code{splitDepvars=1}. Diagonalization is omitted for the update step immediately at the end of Phase if \code{splitDepvars=-1}. - + The value \code{prML = 1} defines the defaults valid in RSiena up to version 1.3.16. For ML estimation with only one dependent variable, \code{prML = 2} may be more efficient.\cr diff --git a/man/simstats0c.Rd b/man/simstats0c.Rd index 1f1b5be..c396fd3 100644 --- a/man/simstats0c.Rd +++ b/man/simstats0c.Rd @@ -11,16 +11,16 @@ } \usage{ simstats0c(z, x, data=NULL, effects=NULL, fromFiniteDiff=FALSE, - returnDeps=FALSE, returnChains=FALSE, + returnDeps=FALSE, returnChains=FALSE, returnChangeContributions=FALSE, byWave=FALSE, returnDataFrame=FALSE, returnLoglik=FALSE) maxlikec(z, x, data=NULL, effects=NULL, - returnChains=FALSE, byGroup = FALSE, - byWave=FALSE, returnDataFrame=FALSE, + returnChains=FALSE, byGroup = FALSE, + byWave=FALSE, returnDataFrame=FALSE, returnLoglik=FALSE, onlyLoglik=FALSE) initializeFRAN(z, x, data, effects, prevAns=NULL, initC, profileData=FALSE, returnDeps=FALSE, returnChains=FALSE, - returnChangeContributions=FALSE, + returnChangeContributions=FALSE, byGroup=FALSE, returnDataFrame=FALSE, byWave=FALSE, returnLoglik=FALSE, onlyLoglik=FALSE) terminateFRAN(z, x) @@ -28,7 +28,7 @@ terminateFRAN(z, x) \arguments{ \item{z}{Control object, passed in automatically in \code{\link{siena}}.} \item{x}{A sienaAlgorithm object, passed in automatically in \code{\link{siena}}.} - \item{data}{A \code{\link{sienadata}} object as returned by + \item{data}{A \code{\link{sienadata}} object as returned by \code{\link{make_data_rsiena}}.} \item{effects}{A sienaEffects object as returned by \code{\link{make_specification}}.} @@ -61,7 +61,7 @@ terminateFRAN(z, x) the new model will be used as initial values, but phase 1 will still be carried out. If the results used as \code{prevAns} are a reasonable starting point, - this will increase the efficiency of the algorithm. } + this will increase the efficiency of the algorithm. } \item{initC}{If TRUE, call is to setup the data and model in C++. For use with multiple processes only.} \item{profileData}{Boolean to force dumping of the data for profiling @@ -105,9 +105,9 @@ terminateFRAN(z, x) value of \code{returnDataFrame}. Only if \code{returnChains} is TRUE.} \item{changeContributions}{A list of sampled chains, one for - each period. Each list consists a list for each dependent variable, each - of which consists of a list for each period, each component of which - is a matrix of effects times choices containing the changeContributions + each period. Each list consists a list for each dependent variable, each + of which consists of a list for each period, each component of which + is a matrix of effects times choices containing the changeContributions (+- change statistics) for each ministep. \cr Only if \code{returnChangeContributions} is TRUE.} \item{accepts}{Number of accepted MH steps by dependent variable @@ -131,7 +131,7 @@ mynet1 <- as_dependent_rsiena(array(c(tmp3, tmp4), dim=c(32, 32, 2))) mydata <- make_data_rsiena(mynet1) myeff <- make_specification(mydata) myeff <- set_effect(myeff, transTrip) -myalgorithm <- sienaAlgorithmCreate(fn=simstats0c, +myalgorithm <- sienaAlgorithmCreate(fn=simstats0c, nsub=2, n3=100, projname=NULL) ans <- siena07(myalgorithm, data=mydata, effects=myeff, batch=TRUE) } diff --git a/src/model/effects/DyadicCovariateAvAltEffect.cpp b/src/model/effects/DyadicCovariateAvAltEffect.cpp index 774bd07..efb94ba 100644 --- a/src/model/effects/DyadicCovariateAvAltEffect.cpp +++ b/src/model/effects/DyadicCovariateAvAltEffect.cpp @@ -35,9 +35,9 @@ DyadicCovariateAvAltEffect::DyadicCovariateAvAltEffect( // Indicates that the dyadic covariate is used as a weight; // if not, used as the variable. this->lpar2 = (pEffectInfo->internalEffectParameter() >= 2); - // Indicates wether in or outgoing ties should be used - this->loutgoing = outgoing; // specifies type of denominator + this->loutgoing = outgoing; + // Indicates wether in or outgoing ties should be used if (!lasWeight) {lpar2 = false;} } diff --git a/tests/newparallel.R b/tests/newparallel.R index d70efc2..c3c6178 100644 --- a/tests/newparallel.R +++ b/tests/newparallel.R @@ -331,5 +331,8 @@ myalg <- set_algorithm_saom(nsub=2, n3=50, cond=FALSE, seed=5, simOnly=TRUE, thetaValue=thv) print('test24') (ans <- siena(mymodel, data=mydata, effects=myeff, control_algo=myalg, batch=TRUE, silent=TRUE)) +print('test25') +effectsDocumentation() ## delete output files if (file.exists('mydata_out.txt')){unlink('mydata_out.txt')} +if (file.exists('effects.html')){unlink('effects.html')} diff --git a/tests/newparallel.Rout.save b/tests/newparallel.Rout.save index bd76c84..dfe5846 100644 --- a/tests/newparallel.Rout.save +++ b/tests/newparallel.Rout.save @@ -1725,9 +1725,14 @@ Simulated statistics are in x$sf, where x is the created object. Total of 605 iteration steps. +> print('test25') +[1] "test25" +> effectsDocumentation() +Effects documentation written to file effects.html . > ## delete output files > if (file.exists('mydata_out.txt')){unlink('mydata_out.txt')} +> if (file.exists('effects.html')){unlink('effects.html')} > > proc.time() user system elapsed - 42.39 0.81 43.34 + 41.65 1.17 43.81