diff --git a/.Rbuildignore b/.Rbuildignore index 09e9ee9..82cd07b 100755 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -18,7 +18,7 @@ .*\.doc .*\.pdf # Misc -README[.]Rmd +README[.](R|q)md ^README\_files$ [.]travis[.]yml ^appveyor\.yml$ @@ -39,4 +39,5 @@ makefile ^netdiffuseR\.tar\.gz$ ^\.github netdiffuseR\.Rcheck - +^\.devcontainer$ +^\.vscode$ \ No newline at end of file diff --git a/.devcontainer/.vscode/settings.json b/.devcontainer/.vscode/settings.json new file mode 100644 index 0000000..d6ef489 --- /dev/null +++ b/.devcontainer/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "r.plot.useHttpgd": true, + "r.alwaysUseActiveTerminal": true +} \ No newline at end of file diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..39a03aa --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,16 @@ +FROM rocker/tidyverse:4.4.0 + +# RUN \ +# echo 'options(repos=c(CRAN="https://packagemanager.posit.co/cran/__linux__/bookworm/latest"))' >> ~/.Rprofile && \ +# Rscript --vanilla -e 'getOption("repos")' + +# Adding R packages +RUN install2.r Rcpp sna network networkDynamic Matrix MASS MatchIt SparseM igraph \ + viridisLite covr testthat knitr rmarkdown ape RSiena survival RcppArmadillo + +RUN install2.r languageserver httpgd + +RUN apt-get update && apt-get install --no-install-recommends -y valgrind gdb \ + libglpk-dev + +CMD ["bash"] diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..8b58911 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,36 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/cpp +{ + "name": "epiworldR", + "build": { + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": [ + "reditorsupport.r", + "rdebugger.r-debugger", + "quarto.quarto", + "tianyishi.rmarkdown" + ] + } + }, + "mounts": [ + // Mount the .vscode configuration into the container + "source=${localWorkspaceFolder}/.devcontainer/.vscode,target=/workspaces/${localWorkspaceFolderBasename}/.vscode,type=bind,consistency=cached" + ] + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "gcc -v", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.github/workflows/r.yml b/.github/workflows/r.yml index ed9c1b2..8472306 100644 --- a/.github/workflows/r.yml +++ b/.github/workflows/r.yml @@ -26,6 +26,7 @@ jobs: - {os: macOS-latest, r: 'release'} - {os: ubuntu-latest, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} - {os: ubuntu-latest, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} + - {os: ubuntu-latest, r: 'devel', valgrind: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} env: R_REMOTES_NO_ERRORS_FROM_WARNINGS: true @@ -70,6 +71,7 @@ jobs: shell: Rscript {0} - name: Check + if: ${{ matrix.config.valgrind != true }} env: _R_CHECK_CRAN_INCOMING_REMOTE_: false run: | @@ -77,9 +79,36 @@ jobs: rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran"), error_on = "error", check_dir = "check") shell: Rscript {0} + - name: Setup valgrind + if: ${{ matrix.config.valgrind == true }} + run: | + sudo apt-get update + sudo apt-get install -y valgrind --no-install-recommends + shell: bash + + - name: Check with Valgrind + if: ${{ matrix.config.valgrind == true }} + env: + _R_CHECK_CRAN_INCOMING_REMOTE_: false + run: | + options(crayon.enabled = TRUE) + rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran", "--use-valgrind"), error_on = "error", check_dir = "check") + shell: Rscript {0} + - name: Upload check results if: failure() uses: actions/upload-artifact@main with: name: ${{ runner.os }}-r${{ matrix.config.r }}-results path: check + + - name: Build the package + if: ${{ matrix.config.os == 'ubuntu-latest' && (matrix.config.r == 'release' || matrix.config.r == 'devel') && (matrix.config.valgrind != true) }} + run: R CMD build . + + - uses: actions/upload-artifact@v4 + if: ${{ matrix.config.os == 'ubuntu-latest' && (matrix.config.r == 'release' || matrix.config.r == 'devel') && (matrix.config.valgrind != true) }} + with: + name: netdiffuseR-built-package-${{ matrix.config.os }}-${{ matrix.config.r }} + path: netdiffuseR_*.tar.gz + retention-days: 7 diff --git a/DESCRIPTION b/DESCRIPTION index 50780a1..0d960f0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: netdiffuseR Title: Analysis of Diffusion and Contagion Processes on Networks -Version: 1.22.7 +Version: 1.23.0 Authors@R: c( person("George", "Vega Yon", email="g.vegayon@gmail.com", role=c("aut", "cre"), comment=c(ORCID = "0000-0002-3171-0844", what="Rewrite functions with Rcpp, plus new features") @@ -51,7 +51,7 @@ Suggests: survival VignetteBuilder: knitr LinkingTo: Rcpp, RcppArmadillo -RoxygenNote: 7.3.1 +RoxygenNote: 7.3.2 Encoding: UTF-8 URL: https://github.com/USCCANA/netdiffuseR, https://USCCANA.github.io/netdiffuseR/ @@ -64,6 +64,7 @@ Collate: 'adjmat.r' 'bass.r' 'bootnet.r' + 'citer_environment.R' 'data.r' 'diffnet-c.R' 'diffnet-class.r' diff --git a/Makefile b/Makefile index e98edc8..832637c 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,22 @@ -VERSION:=$(shell Rscript -e 'x<-readLines("DESCRIPTION");cat(gsub(".+[:]\\s*", "", x[grepl("^Vers", x)]))') - -install: netdiffuseR_$(VERSION).tar.gz - R CMD INSTALL netdiffuseR_$(VERSION).tar.gz - -netdiffuseR_$(VERSION).tar.gz: */*.R inst/NEWS README.md +help: + @echo "Makefile for netdiffuseR package" + @echo "Usage:" + @echo " make install - Install the package" + @echo " make build - Build the package source tarball" + @echo " make check - Check the package with R CMD check" + @echo " make checkv - Check the package with R CMD check using Valgrind" + @echo " make clean - Clean up the build artifacts" + @echo " make docs - Generate documentation" + +install: + R CMD INSTALL . + +build: R CMD build . -inst/NEWS: NEWS.md - Rscript -e "rmarkdown::pandoc_convert('NEWS.md', 'plain', output='inst/NEWS')"&& \ - head -n 80 inst/NEWS - README.md: README.Rmd Rscript -e 'rmarkdown::render("README.Rmd")' -.PHONY: check checkv clean - check: netdiffuseR_$(VERSION).tar.gz R CMD check --as-cran netdiffuseR_$(VERSION).tar.gz @@ -22,8 +24,9 @@ checkv: netdiffuseR_$(VERSION).tar.gz R CMD check --as-cran --use-valgrind netdiffuseR_$(VERSION).tar.gz clean: - rm -rf netdiffuseR.Rcheck + rm -rf netdiffuseR.Rcheck src/*.so src/*.o -man/moran.Rd: R/* src/*.cpp src/*.h - Rscript --vanilla -e 'roxygen2::roxygenize()' +docs: + Rscript --vanilla -e 'devtools::document()' +.PHONY: check checkv clean install docs diff --git a/NEWS.md b/NEWS.md index 364f9ee..a860075 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,10 @@ +# Changes in netdiffuseR version 1.23.0 (2025-06-10) + +* New methods for simulating multi-diffusion models. + +* It is now possible to simulate diffusions with general disadoption functions. + + # Changes in netdiffuseR version 1.22.7 (2024-09-18) * Minor changes to testing (skip warnings). diff --git a/R/citer_environment.R b/R/citer_environment.R new file mode 100644 index 0000000..e6b570a --- /dev/null +++ b/R/citer_environment.R @@ -0,0 +1,20 @@ +# file_version: f6ffa5cc103728c81c977e9101df287d +# citer_version: 0.0.9000 +# DO NOT EDIT THIS BY HAND! +# This document was automatically generated by the `citer` package. +# tools::md5sum() + +# Citer Environment Setup +citation_on_load <- function() { + + pkg_name <- "netdiffuseR" + + packageStartupMessage( + "Thank you for using ", pkg_name, "! ", + "Please consider citing it in your work.\n", + "You can find the citation information by running\n citation(\"", + pkg_name, + "\")" + ) + +} diff --git a/R/diffnet-class.r b/R/diffnet-class.r index 1858da8..d92ec8d 100644 --- a/R/diffnet-class.r +++ b/R/diffnet-class.r @@ -6,8 +6,13 @@ make_col_names <- function(n, is.dynamic, prefix="v.") { } # Checks attributes to be added to a diffnet object -check_as_diffnet_attrs <- function(attrs, meta, is.dynamic, id.and.per.vars=NULL, - attr.class="vertex") { +check_as_diffnet_attrs <- function( + attrs, + meta, is.dynamic, + id.and.per.vars=NULL, + attr.class="vertex" + ) { + # Getting meta n <- meta$n nper <- meta$nper @@ -350,7 +355,7 @@ check_as_diffnet_attrs <- function(attrs, meta, is.dynamic, id.and.per.vars=NULL #' or static (\code{"static"}). #' @param as.df Logical scalar. When TRUE returns a data.frame. #' @param name Character scalar. Name of the diffusion network (descriptive). -#' @param behavior Character scalar. Name of the behavior been analyzed (innovation). +#' @param behavior Character vector. Name of the behavior(s) been analyzed (innovation). #' #' @seealso Default options are listed at \code{\link{netdiffuseR-options}} #' @details @@ -527,7 +532,7 @@ check_as_diffnet_attrs <- function(attrs, meta, is.dynamic, id.and.per.vars=NULL #' \item \code{undirected}: Logical scalar. #' \item \code{multiple}: Logical scalar. #' \item \code{name}: Character scalar. -#' \item \code{behavior}: Character scalar. +#' \item \code{behavior}: A list of character scalars. #' } #' } #' @author George G. Vega Yon & Aníbal Olivera M. @@ -555,16 +560,20 @@ as_diffnet.networkDynamic <- function(graph, toavar, ...) { #' @export #' @rdname diffnet-class -new_diffnet <- function(graph, toa, t0=min(toa, na.rm = TRUE), t1=max(toa, na.rm = TRUE), - vertex.dyn.attrs = NULL, vertex.static.attrs= NULL, - id.and.per.vars = NULL, - graph.attrs = NULL, - undirected = getOption("diffnet.undirected"), - self = getOption("diffnet.self"), - multiple = getOption("diffnet.multiple"), - name = "Diffusion Network", - behavior = "Unspecified" - ) { +new_diffnet <- function( + graph, toa, + t0=min(toa, na.rm = TRUE), + t1=max(toa, na.rm = TRUE), + vertex.dyn.attrs = NULL, + vertex.static.attrs = NULL, + id.and.per.vars = NULL, + graph.attrs = NULL, + undirected = getOption("diffnet.undirected"), + self = getOption("diffnet.self"), + multiple = getOption("diffnet.multiple"), + name = "Diffusion Network", + behavior = NULL +) { # Step 0.0: Check if its diffnet! -------------------------------------------- if (inherits(graph, "diffnet")) { @@ -574,9 +583,19 @@ new_diffnet <- function(graph, toa, t0=min(toa, na.rm = TRUE), t1=max(toa, na.rm # Step 0.1: Setting num_of_behavior ------------------------------------------ - if (inherits(toa, "matrix")) { + if (inherits(toa, "matrix")) num_of_behaviors <- dim(toa)[2] - } else {num_of_behaviors <- 1} + else + num_of_behaviors <- 1 + + if (length(behavior) == 0L) + behavior <- rep("Unknown", num_of_behaviors) + else if (length(behavior) != num_of_behaviors) + stop( + "Length of -behavior- must be equal to the number of behaviors in -toa-." + ) + else if (!inherits(behavior, "list")) + behavior <- as.list(behavior) # Step 1.1: Check graph ------------------------------------------------------ meta <- classify_graph(graph) @@ -585,27 +604,30 @@ new_diffnet <- function(graph, toa, t0=min(toa, na.rm = TRUE), t1=max(toa, na.rm # Step 1.2: Checking that lengths fit - if (num_of_behaviors == 1) { - if (length(toa)!=meta$n){ stop("-graph- and -toa- have different lengths (", meta$n, " and ", length(toa), - " respectively). ", "-toa- should be of length n (number of vertices).") } - } else { - if (length(toa[,1])!=meta$n) {stop("-graph- and -toa[,1]- have different lengths (", meta$n, " and ", length(toa[,1]), - " respectively). ", "-toa- should be of length n (number of vertices).") } + if ((num_of_behaviors == 1L) && (length(toa) != meta$n)) { + + stop( + "-graph- and -toa- have different lengths (", meta$n, " and ", + length(toa), + " respectively). -toa- should be of length n (number of vertices)." + ) + + } else if ((num_of_behaviors > 1L) && length(toa[, 1L])!=meta$n) { + + stop( + "-graph- and -toa[, 1]- have different lengths (", meta$n, " and ", + length(toa[, 1L]), + " respectively). ", "-toa- should be of length n (number of vertices)." + ) + } - # Step 2.1: Checking class of TOA and coercing if necessary ------------------- - if (num_of_behaviors==1) { - if (!inherits(toa, "integer")) { - warning("Coercing -toa- into integer.") - toa <- as.integer(toa) - } - } else { - for (q in 1:num_of_behaviors) { - if (!inherits(toa[,q], "integer")) { - warning("Coercing -toa- into integer.") - toa[,q] <- as.integer(toa[,q]) - } - } + # Step 2.1: Checking class of TOA and coercing if necessary + if (!inherits(toa, "integer")) { + + warning("Coercing -toa- into integer.") + toa[] <- as.integer(toa) + } # Step 2.2: Checking names of toa @@ -624,42 +646,66 @@ new_diffnet <- function(graph, toa, t0=min(toa, na.rm = TRUE), t1=max(toa, na.rm if (num_of_behaviors==1) { if (meta$type != "static") { + tdiff <- meta$nper - ncol(mat$adopt) if (tdiff < 0) - stop("Range of -toa- is bigger than the number of slices in -graph- (", - ncol(mat$adopt), " and ", length(graph) ," respectively). ", - "There must be at least as many slices as range of toa.") + stop( + "Range of -toa- is bigger than the number of slices in -graph- (", + ncol(mat$adopt), " and ", length(graph) ," respectively). ", + "There must be at least as many slices as range of toa." + ) else if (tdiff > 0) - stop("Range of -toa- is smaller than the number of slices in -graph- (", - ncol(mat$adopt), " and ", length(graph) ," respectively). ", - "Please provide lower and upper boundaries for the values in -toa- ", - "using -t0- and -t- (see ?toa_mat).") + stop( + "Range of -toa- is smaller than the number of slices in -graph- (", + ncol(mat$adopt), " and ", length(graph) ," respectively). ", + "Please provide lower and upper boundaries for the values in -toa- ", + "using -t0- and -t- (see ?toa_mat)." + ) + } else { - graph <- lapply(1:ncol(mat$adopt), function(x) methods::as(graph, "dgCMatrix")) + + graph <- lapply( + 1:ncol(mat$adopt), function(x) methods::as(graph, "dgCMatrix") + ) + meta <- classify_graph(graph) + } } else { if (meta$type != "static") { + tdiff <- meta$nper - ncol(mat[[1]]$adopt) if (tdiff < 0) - stop("Range of -toa- is bigger than the number of slices in -graph- (", - ncol(mat[[1]]$adopt), " and ", length(graph) ," respectively). ", - "There must be at least as many slices as range of toa.") + stop( + "Range of -toa- is bigger than the number of slices in -graph- (", + ncol(mat[[1]]$adopt), " and ", length(graph) ," respectively). ", + "There must be at least as many slices as range of toa." + ) else if (tdiff > 0) - stop("Range of -toa- is smaller than the number of slices in -graph- (", - ncol(mat[[1]]$adopt), " and ", length(graph) ," respectively). ", - "Please provide lower and upper boundaries for the values in -toa- ", - "using -t0- and -t- (see ?toa_mat).") + stop( + "Range of -toa- is smaller than the number of slices in -graph- (", + ncol(mat[[1]]$adopt), " and ", length(graph) ," respectively). ", + "Please provide lower and upper boundaries for the values in -toa- ", + "using -t0- and -t- (see ?toa_mat)." + ) + } else { - graph <- lapply(1:ncol(mat[[1]]$adopt), function(x) methods::as(graph, "dgCMatrix")) + + graph <- lapply( + 1:ncol(mat[[1]]$adopt), function(x) methods::as(graph, "dgCMatrix") + ) + meta <- classify_graph(graph) + } } # labels of the time periods - if (num_of_behaviors==1) { + if (num_of_behaviors == 1) { meta$pers <- as.integer(colnames(mat$adopt)) - } else {meta$pers <- as.integer(colnames(mat[[1]]$adopt))} # same for all behaviors + } else { + meta$pers <- as.integer(colnames(mat[[1]]$adopt)) + } # same for all behaviors # Step 4.0: Checking the attributes ------------------------------------------ @@ -688,48 +734,59 @@ new_diffnet <- function(graph, toa, t0=min(toa, na.rm = TRUE), t1=max(toa, na.rm meta$self <- self meta$undirected <- undirected meta$multiple <- multiple - meta$name <- ifelse(!length(name), "", ifelse(is.na(name), "", - as.character(name))) - meta$version <- utils::packageVersion("netdiffuseR") + meta$name <- ifelse( + !length(name), "", ifelse(is.na(name), "", as.character(name)) + ) - # Removing dimnames - graph <- Map(function(x) Matrix::unname(x), x=graph) - #dimnames(toa) <- NULL + meta$version <- utils::packageVersion("netdiffuseR") + graph <- Map(function(x) Matrix::unname(x), x=graph) + + if (num_of_behaviors == 1) { + + meta$behavior <- behavior - if (num_of_behaviors==1) { - meta$behavior <- ifelse(!length(behavior), "", ifelse(is.na(behavior), "", - as.character(behavior))) dimnames(mat$adopt) <- NULL dimnames(mat$cumadopt) <- NULL adopt <- mat$adopt cumadopt <- mat$cumadopt + } else { - meta$behavior <- paste(unlist(behavior), collapse = ", ") + + meta$behavior <- behavior for (q in 1:num_of_behaviors) { dimnames(mat[[q]]$adopt) <- NULL dimnames(mat[[q]]$cumadopt) <- NULL } + adopt <- list() cumadopt <- list() + for (q in 1:num_of_behaviors) { adopt[[q]] <- mat[[q]]$adopt cumadopt[[q]] <- mat[[q]]$cumadopt } + } - return(structure(list( - graph = graph, - toa = toa, - adopt = adopt, - cumadopt = cumadopt, - # Attributes - vertex.static.attrs = vertex.static.attrs, - vertex.dyn.attrs = vertex.dyn.attrs, - graph.attrs = graph.attrs, - meta = meta - ), class="diffnet")) + return( + structure( + list( + graph = graph, + toa = toa, + adopt = adopt, + cumadopt = cumadopt, + # Attributes + vertex.static.attrs = vertex.static.attrs, + vertex.dyn.attrs = vertex.dyn.attrs, + graph.attrs = graph.attrs, + meta = meta + ), + class="diffnet" + ) + ) + } #' @export diff --git a/R/diffnet-methods.r b/R/diffnet-methods.r index 239634d..2a12e98 100644 --- a/R/diffnet-methods.r +++ b/R/diffnet-methods.r @@ -113,7 +113,7 @@ print.diffnet <- function(x, ...) { cat( "Dynamic network of class -diffnet-", paste(" Name :", meta$name), - paste(" Behavior :", meta$behavior), + paste(" Behavior :", paste(meta$behavior, collapse=", ")), paste(" # of nodes :", nodesl ), paste(" # of time periods :", meta$nper, sprintf("(%d - %d)", meta$pers[1], meta$pers[meta$nper])), paste(" Type :", ifelse(meta$undirected, "undirected", "directed")), @@ -324,7 +324,7 @@ summary.diffnet <- function( "Name : ", meta$name, "\n") if (single) { - cat(" Behavior : ", meta$behavior, "\n", + cat(" Behavior : ", meta$behavior[[1L]], "\n", rule,"\n",sep="") cat(header,"\n") cat(hline, "\n") @@ -333,9 +333,9 @@ summary.diffnet <- function( paste("Left censoring :", sprintf("%3.2f (%d)", lc/meta$n, lc)), "\n", paste("Right centoring :", sprintf("%3.2f (%d)", rc/meta$n, rc)), "\n") } else { - beh_names <- strsplit(meta$behavior, ", ")[[1]] + beh_names <- meta$behavior for (q in 1:length(object$cumadopt)) { - cat("\n Behavior : ", beh_names[q], "\n", + cat("\n Behavior : ", beh_names[[q]], "\n", rule,"\n",sep="") cat(header,"\n") cat(hline, "\n") @@ -745,7 +745,7 @@ plot_diffnet.default <- function( #' @return Invisible. A data frame with the calculated coordinates, including: #' `toa`, `threshold`, and `jit` (a jittered version of `toa`). #' @author George G. Vega Yon -plot_threshold <- function(graph, expo, vertex.label,...) UseMethod("plot_threshold") +plot_threshold <- function(graph, expo,...) UseMethod("plot_threshold") #' @export #' @rdname plot_threshold @@ -768,15 +768,21 @@ plot_threshold.diffnet <- function(graph, expo, ...) { args$toa <- graph$toa } - args$vertex.label <- nodes(graph) + if (length(args$vertex.label) == 0L) + args$vertex.label <- nodes(graph) + do.call(plot_threshold.default, - c(list(graph = graph$graph, expo=expo), args)) + c(list(graph = graph$graph, expo = expo), args)) } #' @export #' @rdname plot_threshold plot_threshold.array <- function(graph, expo, ...) { - plot_threshold.default(as_dgCMatrix(graph), expo = expo, ...) + plot_threshold.default( + as_dgCMatrix(graph), + expo = expo, + ... + ) } #' @export @@ -966,12 +972,15 @@ plot_threshold.default <- function( # Positioning labels can be harsh, so we try with this algorithm if (!length(vertex.label)) vertex.label <- 1:n - graphics::text(x=jit, y=y, labels = vertex.label, - pos = vertex.label.pos, - cex = vertex.label.cex, - col = vertex.label.color, - adj = vertex.label.adj - ) + graphics::text( + x=jit, + y=y, + labels = vertex.label, + pos = vertex.label.pos, + cex = vertex.label.cex, + col = vertex.label.color, + adj = vertex.label.adj + ) # par(oldpar) diff --git a/R/graph_data.r b/R/graph_data.r index d8d4a94..42e8542 100644 --- a/R/graph_data.r +++ b/R/graph_data.r @@ -41,9 +41,6 @@ #' @family graph formats NULL - -as_generic_graph <- function(graph) UseMethod("as_generic_graph") - # Method for igraph objects as_generic_graph.igraph <- function(graph) { @@ -65,7 +62,7 @@ as_generic_graph.igraph <- function(graph) { undirected = FALSE, # For now we will assume it is undirected multiple = FALSE, # And !multiple class = "igraph" - )) + )) add_to_generic_graph("ans", "meta", meta, env) return(ans) @@ -96,7 +93,7 @@ as_generic_graph.network <- function(graph) { undirected = !network::is.directed(graph), multiple = network::is.multiplex(graph), self = network::has.loops(graph) - ) + ) ord <- network::network.vertex.names(graph) ord <- match(ord, rownames(adjmat)) @@ -221,7 +218,7 @@ classify_graph <- function(graph) { # Step 4.2.1: Must keep uniqueness if (length(unique(pers)) != t) stop("When coercing names(graph) into integer,", - "some slices acquired the same name.") + "some slices acquired the same name.") } return(invisible(list( diff --git a/R/options.R b/R/options.R index 19e78e2..cc045d7 100644 --- a/R/options.R +++ b/R/options.R @@ -18,6 +18,7 @@ #' @author George G. Vega Yon NULL .onLoad <- function(libname, pkgname) { + citation_on_load() options( diffnet.undirected=FALSE, diffnet.self=FALSE, diff --git a/R/package-doc.r b/R/package-doc.r index 00a8fdb..5c90c51 100644 --- a/R/package-doc.r +++ b/R/package-doc.r @@ -18,13 +18,8 @@ #' #' @section Workshops and Tutorials: #' -#' Online you can find several learning resources: -#' -#' \itemize{ -#' \item Sunbelt 2016 \url{https://github.com/USCCANA/netdiffuser-sunbelt2016} -#' \item NASN 2017 \url{https://github.com/USCCANA/netdiffuser-nasn2017} -#' \item Sunbelt 2018 \url{https://github.com/USCCANA/netdiffuser-sunbelt2018} -#' } +#' Online you can find several learning resources, particularly, at the +#' netdiffuseR workshop website: . #' #' @aliases netdiffuseR-package #' @name netdiffuseR diff --git a/R/random_graph.R b/R/random_graph.R index 6e6ce65..c531684 100644 --- a/R/random_graph.R +++ b/R/random_graph.R @@ -23,7 +23,7 @@ #' networks are uncorrelated. #' @references #' Barabasi, Albert-Laszlo. "Network science book" Retrieved November 1 (2015) -#' \url{https://barabasi.com/book/network-science}. +#' \url{https://networksciencebook.com}. #' @return A graph represented by an adjacency matrix (if \code{t=1}), or an array of #' adjacency matrices (if \code{t>1}). #' @export @@ -164,7 +164,7 @@ rgraph_er <- function(n=10, t=1, p=0.01, undirected=getOption("diffnet.undirecte #' Networks. Science, 286(5439), 509–512. \doi{10.1126/science.286.5439.509} #' #' Albert-László Barabási. (2016). Network Science: (1st ed.). Cambridge University Press. -#' Retrieved from \url{https://barabasi.com/book/network-science} +#' Retrieved from \url{https://networksciencebook.com} #' #' De Almeida, M. L., Mendes, G. A., Madras Viswanathan, G., & Da Silva, L. R. (2013). #' Scale-free homophilic network. European Physical Journal B, 86(2). diff --git a/R/rdiffnet.r b/R/rdiffnet.r index 21f7bdb..122938f 100644 --- a/R/rdiffnet.r +++ b/R/rdiffnet.r @@ -169,7 +169,10 @@ #' return(list_disadopt) #' } #' -#' diffnet_6 <- rdiffnet(seed.graph = graph, t = 10, disadopt = random_dis, seed.p.adopt = list(0.1, 0.1)) +#' diffnet_6 <- rdiffnet( +#' seed.graph = graph, t = 10, disadopt = random_dis, +#' seed.p.adopt = list(0.1, 0.1) +#' ) #' #' @author George G. Vega Yon & Aníbal Olivera M. #' @name rdiffnet @@ -370,6 +373,19 @@ rdiffnet_multiple <- function( } +default_rewire.args <- list( + p = .1, + undirected = getOption("diffnet.undirected", FALSE), + self = getOption("diffnet.self", FALSE), + warn = FALSE +) + +default_exposure.args <- list( + outgoing = TRUE, + valued = getOption("diffnet.valued", FALSE), + normalized = TRUE +) + #' @rdname rdiffnet #' @export rdiffnet <- function( @@ -390,13 +406,13 @@ rdiffnet <- function( ) { # Checking options - if (!length(rewire.args[["p"]])) rewire.args[["p"]] <- .1 - if (!length(rewire.args[["undirected"]])) rewire.args[["undirected"]] <- getOption("diffnet.undirected", FALSE) - if (!length(rewire.args[["self"]])) rewire.args[["self"]] <- getOption("diffnet.self", FALSE) + for (arg in names(default_rewire.args)) + if (!length(rewire.args[[arg]])) + rewire.args[[arg]] <- default_rewire.args[[arg]] - if (!length(exposure.args[["outgoing"]])) exposure.args[["outgoing"]] <- TRUE - if (!length(exposure.args[["valued"]])) exposure.args[["valued"]] <- getOption("diffnet.valued", FALSE) - if (!length(exposure.args[["normalized"]])) exposure.args[["normalized"]] <- TRUE + for (arg in names(default_exposure.args)) + if (!length(exposure.args[[arg]])) + exposure.args[[arg]] <- default_exposure.args[[arg]] if (inherits(exposure.args[["attrs"]], "matrix")) { # Checking if the attrs matrix is has dims n x t @@ -416,7 +432,7 @@ rdiffnet <- function( meta <- classify_graph(sgraph) # Was n set? - if (!missing(n) && n != meta$n) { + if (!missing(n) && (n != meta$n)) { warning("While the user set n=",n,", nnodes(seed.graph)=", meta$n,". The later will be used.") n <- meta$n } @@ -449,10 +465,10 @@ rdiffnet <- function( # Step 1.0: Setting the seed nodes ----------------------------------------- - rdiffnet_args <- rdiffnet_validate_args(seed.p.adopt, seed.nodes, behavior) - seed.p.adopt <- rdiffnet_args$seed.p.adopt - seed.nodes <- rdiffnet_args$seed.nodes - behavior <- rdiffnet_args$behavior + rdiffnet_args <- rdiffnet_validate_args(seed.p.adopt, seed.nodes, behavior) + seed.p.adopt <- rdiffnet_args$seed.p.adopt + seed.nodes <- rdiffnet_args$seed.nodes + behavior <- rdiffnet_args$behavior num_of_behaviors <- rdiffnet_args$num_of_behaviors # Step 1.1: Number of initial adopters @@ -462,13 +478,21 @@ rdiffnet <- function( for (i in 1:num_of_behaviors) { if ((seed.p.adopt[[i]] > 1) | (seed.p.adopt[[i]] < 0)) { - stop(paste("The proportion of initial adopters for behavior", i, "should be a number in [0,1]")) + stop( + paste( + "The proportion of initial adopters for behavior", i, + "should be a number in [0,1]" + ) + ) } if (n*seed.p.adopt[[i]] < 1) { - warning(paste("Set of initial adopters for behavior", i, "set to 1.")) + warning( + paste("Set of initial adopters for behavior", i, "set to 1.") + ) } n0[[i]] <- max(1, n * seed.p.adopt[[i]]) + } # Step 1.2: finding the nodes @@ -614,21 +638,35 @@ rdiffnet_validate_args <- function(seed.p.adopt, seed.nodes, behavior) { # The class of seed.p.adopt determines if is a single or multiple diff pross. if (inherits(seed.p.adopt, "list")) { - message(paste("Message: Multi-diffusion behavior simulation selected.", - "Number of behaviors: ", length(seed.p.adopt))) + + message( + paste( + "Message: Multi-diffusion behavior simulation selected.", + "Number of behaviors: ", length(seed.p.adopt)) + ) + multi <- TRUE + } else if (inherits(seed.p.adopt, "numeric")) { - if (length(seed.p.adopt)>1) { - stop(paste("length(seed.p.adopt) =", length(seed.p.adopt), - ", but for multi-diffusion -seed.p.adopt- must be a -list-.")) + if (length(seed.p.adopt) > 1) { + + stop( + paste("length(seed.p.adopt) =", length(seed.p.adopt), + ", but for multi-diffusion -seed.p.adopt- must be a -list-.") + ) + } multi <- FALSE + } else { - stop("The object -seed.p.adopt- must be a -numeric- (for a single behavior diff)", - "or a -list- (multiple behavior diff).") + stop( + "The object -seed.p.adopt- must be a -numeric- (for a single behavior diff)", + "or a -list- (multiple behavior diff)." + ) + } # seed.nodes stuff @@ -755,7 +793,7 @@ split_behaviors <- function(diffnet_obj) { # creates a list, keeping the structure of each element diffnets <- replicate(ncol(diffnet_obj$toa), diffnet_obj, simplify = FALSE) - behaviors_names <- strsplit(diffnet_obj$meta$behavior, ", ")[[1]] + behaviors_names <- diffnet_obj$meta$behavior # loop over the behaviors for (q in 1:ncol(diffnet_obj$toa)) { diff --git a/R/rewire.r b/R/rewire.r index 2cecbd3..e033508 100644 --- a/R/rewire.r +++ b/R/rewire.r @@ -13,6 +13,8 @@ #' @param algorithm Character scalar. Either \code{"swap"}, \code{"endpoints"}, or \code{"qap"} #' (see \code{\link{rewire_qap}}). #' @param althexagons Logical scalar. When \code{TRUE} uses the compact alternating +#' @param warn Logical scalar. If \code{TRUE} (default) shows warnings when +#' recycling the first slice in dynamic graphs. #' hexagons algorithm (currently ignored [on development]). #' @details #' The algorithm \code{"qap"} is described in \code{\link{rewire_qap}}, and only @@ -220,7 +222,8 @@ rewire_graph <- function( undirected = getOption("diffnet.undirected"), pr.change = ifelse(self, 0.5, 1), copy.first = TRUE, - althexagons = FALSE + althexagons = FALSE, + warn = TRUE ) { # Checking undirected (if exists) @@ -229,14 +232,20 @@ rewire_graph <- function( # althexagons is still on development if (althexagons) { althexagons <- FALSE - warning("The option -althexagons- is still on development. So it has been set to FALSE.") + + if (warn) + warning( + "The option -althexagons- is still on development. So it has been set", + " to FALSE." + ) } - if (copy.first) { + if (copy.first && warn) { - message( - "The option -copy.first- is set to TRUE. In this case, the first graph will be ", - "treated as a baseline, and thus, networks after T=1 will be replaced with T-1.", + warning( + "The option -copy.first- is set to TRUE. In this case, the first graph", + " will be treated as a baseline, and thus, networks after T=1 will be ", + "replaced with T-1.", immediate. = TRUE ) diff --git a/R/struct_test.R b/R/struct_test.R index d151dc5..c3a9a87 100644 --- a/R/struct_test.R +++ b/R/struct_test.R @@ -159,6 +159,7 @@ struct_test <- function( rewire.args$undirected <- getOption("diffnet.undirected", FALSE) if (!length(rewire.args$copy.first)) rewire.args$copy.first <- TRUE if (!length(rewire.args$algorithm)) rewire.args$algorithm <- "swap" + if (!length(rewire.args$warn)) rewire.args$warn <- FALSE # Preparing the call to boot rewire.args$graph <- graph @@ -167,8 +168,14 @@ struct_test <- function( } # Calling boot - boot_res <- boot::boot(1, statisticpll, R=R, fn=statistic, rewire.args=rewire.args, - ...) + boot_res <- boot::boot( + 1, + statisticpll, + R = R, + fn = statistic, + rewire.args = rewire.args, + ... + ) # The t0 must be applied with no rewiring! boot_res$t0 <- statistic(graph) diff --git a/README.md b/README.md index b5287d9..b92c041 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,14 @@ + [![R-CMD-check](https://github.com/USCCANA/netdiffuseR/actions/workflows/r.yml/badge.svg)](https://github.com/USCCANA/netdiffuseR/actions/workflows/r.yml) [![codecov.io](https://codecov.io/github/USCCANA/netdiffuseR/coverage.svg?branch=master)](https://app.codecov.io/github/USCCANA/netdiffuseR?branch=master) [![](https://cranlogs.r-pkg.org/badges/netdiffuseR)](https://cran.r-project.org/package=netdiffuseR) [![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/netdiffuseR)](https://cran.r-project.org/package=netdiffuseR) [![](https://cranlogs.r-pkg.org/badges/grand-total/netdiffuseR)](https://cran.r-project.org/package=netdiffuseR) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1039317.svg)](https://doi.org/10.5281/zenodo.1039317) -[![Dependencies](https://tinyverse.netlify.com/badge/netdiffuseR)](https://cran.r-project.org/package=netdiffuseR) +[![Dependencies](https://tinyverse.netlify.app/badge/netdiffuseR)](https://cran.r-project.org/package=netdiffuseR) [![USC’s Department of Preventive -Medicine](https://raw.githubusercontent.com/USCbiostats/badges/master/tommy-uscprevmed-badge.svg)](https://pphs.usc.edu/center/cana/) +Medicine](https://raw.githubusercontent.com/USCbiostats/badges/master/tommy-uscprevmed-badge.svg)](https://keck.usc.edu/cana/)

@@ -23,7 +24,7 @@ Stephanie R. Dyal, Kar-Hai Chu, Heather Wipfli, Kayo Fujimoto, *Diffusion of innovations theory applied to global tobacco control treaty ratification*, Social Science & Medicine, Volume 145, November 2015, Pages 89-97, ISSN 0277-9536 (available -[here](https://www.sciencedirect.com/science/article/pii/S027795361530143X)) +[here](https://doi.org/10.1016/j.socscimed.2015.10.001)). From the description: @@ -51,10 +52,10 @@ citation(package="netdiffuseR") And the actual R package: - Vega Yon G, Valente T (2023). _netdiffuseR: Analysis of Diffusion and - Contagion Processes on Networks_. doi:10.5281/zenodo.1039317 - , R package version 1.22.6, - . + Vega Yon G, Olivera Morales A, Valente T (2025). _netdiffuseR: + Analysis of Diffusion and Contagion Processes on Networks_. + doi:10.5281/zenodo.1039317 , + R package version 1.23.0, . To see these entries in BibTeX format, use 'print(, bibtex=TRUE)', 'toBibtex(.)', or set @@ -64,20 +65,6 @@ citation(package="netdiffuseR") Changelog can be view [here](NEWS.md). -- \[2016-06-02\] A video of the **netdiffuseR** workshop at SUNBELT 2016 - is now online on - [youtube](https://www.youtube.com/playlist?list=PLT-GgRN1lFI4coHDqkRJm3flDw9e1gg2P), - and the workshop materials can be found - [here](https://github.com/USCCANA/netdiffuser-sunbelt2016/) -- \[2016-04-11\] **netdiffuseR** will be on [useR! - 2016](https://user2016.r-project.org/) on as a presentation and on - [IC2S2 - 2016](https://www.kellogg.northwestern.edu/news-events/conference/ic2s2/2016.aspx) - in the posters session. -- \[2016-03-16\] Next CRAN release scheduled for April 11th 2016 (after - the workshop). -- \[2016-02-18\] **netdiffuseR** vers 1.16.2 is now on CRAN! - ## Installation ### CRAN version @@ -91,10 +78,10 @@ install.packages("netdiffuseR") ### Bleeding edge version If you want the latest (unstable) version of **netdiffuseR**, using the -`devtools` package, you can install `netdiffuseR` dev version as follows +`remotes` package, you can install `netdiffuseR` dev version as follows ``` r -devtools::install_github('USCCANA/netdiffuseR', build_vignettes = TRUE) +remotes::install_github('USCCANA/netdiffuseR', build_vignettes = TRUE) ``` You can skip building vignettes by setting `build_vignettes = FALSE` (so @@ -137,21 +124,16 @@ this directly as follows (using the 1.16.3.29 version): ## Tutorials Since starting netdiffuseR, we have done a couple of workshops at -Sunbelt and NASN. Here are the repositories: - -- Sunbelt 2018: - ([source code](https://github.com/USCCANA/netdiffuser-sunbelt2018)) -- NASN 2017: ([source - code](https://github.com/USCCANA/netdiffuser-nasn2017)) -- Sunbelt 2016: +Sunbelt and NASN. Past and current workshops can be found at + ## Presentations - ic2s2 2016 Evanston, IL: - (poster) + https://github.com/USCCANA/netdiffuser-ic2s22016 (poster) - useR! 2016 Stanford, CA: - (slides) -- useR! 2016: + https://github.com/USCCANA/netdiffuser-user2016 (slides) +- useR! 2016: https://github.com/USCCANA/netdiffuser-user2016 ## Examples @@ -161,12 +143,12 @@ This example has been taken from the package’s vignettes: library(netdiffuseR) ``` - ## - ## Attaching package: 'netdiffuseR' - ## The following object is masked from 'package:base': - ## - ## %*% + Attaching package: 'netdiffuseR' + + The following object is masked from 'package:base': + + %*% ### Infectiousness and Susceptibility @@ -180,7 +162,7 @@ toa <- sample(c(1:(1+nper-1), NA), n, TRUE) head(toa) ``` - ## [1] 16 3 14 3 13 5 + [1] 16 3 14 3 13 5 ``` r # Creating a diffnet object @@ -188,70 +170,71 @@ diffnet <- as_diffnet(graph, toa) diffnet ``` - ## Dynamic network of class -diffnet- - ## Name : Diffusion Network - ## Behavior : Unspecified - ## # of nodes : 100 (1, 2, 3, 4, 5, 6, 7, 8, ...) - ## # of time periods : 20 (1 - 20) - ## Type : directed - ## Final prevalence : 0.95 - ## Static attributes : - - ## Dynamic attributes : - + Dynamic network of class -diffnet- + Name : Diffusion Network + Behavior : Unknown + # of nodes : 100 (1, 2, 3, 4, 5, 6, 7, 8, ...) + # of time periods : 20 (1 - 20) + Type : directed + Num of behaviors : 1 + Final prevalence : 0.95 + Static attributes : - + Dynamic attributes : - ``` r summary(diffnet) ``` - ## Diffusion network summary statistics - ## Name : Diffusion Network - ## Behavior : Unspecified - ## ----------------------------------------------------------------------------- - ## Period Adopters Cum Adopt. (%) Hazard Rate Density Moran's I (sd) - ## -------- ---------- ---------------- ------------- --------- ---------------- - ## 1 8 8 (0.08) - 0.50 -0.01 (0.00) - ## 2 3 11 (0.11) 0.03 0.50 -0.01 (0.00) - ## 3 6 17 (0.17) 0.07 0.51 -0.01 (0.00) - ## 4 3 20 (0.20) 0.04 0.49 -0.01 (0.00) - ## 5 9 29 (0.29) 0.11 0.50 -0.01 (0.00) - ## 6 5 34 (0.34) 0.07 0.50 -0.01 (0.00) - ## 7 2 36 (0.36) 0.03 0.51 -0.01 (0.00) - ## 8 3 39 (0.39) 0.05 0.50 -0.01 (0.00) - ## 9 5 44 (0.44) 0.08 0.50 -0.01 (0.00) - ## 10 1 45 (0.45) 0.02 0.49 -0.01 (0.00) - ## 11 3 48 (0.48) 0.05 0.50 -0.01 (0.00) - ## 12 6 54 (0.54) 0.12 0.50 -0.01 (0.00) - ## 13 8 62 (0.62) 0.17 0.50 -0.01 (0.00) - ## 14 9 71 (0.71) 0.24 0.50 -0.01 (0.00) - ## 15 5 76 (0.76) 0.17 0.50 -0.00 (0.00) ** - ## 16 7 83 (0.83) 0.29 0.50 -0.01 (0.00) - ## 17 5 88 (0.88) 0.29 0.49 -0.00 (0.00) *** - ## 18 4 92 (0.92) 0.33 0.50 -0.01 (0.00) - ## 19 1 93 (0.93) 0.12 0.50 -0.01 (0.00) - ## 20 2 95 (0.95) 0.29 0.50 -0.01 (0.00) - ## ----------------------------------------------------------------------------- - ## Left censoring : 0.08 (8) - ## Right centoring : 0.05 (5) - ## # of nodes : 100 - ## - ## Moran's I was computed on contemporaneous autocorrelation using 1/geodesic - ## values. Significane levels *** <= .01, ** <= .05, * <= .1. + Diffusion network summary statistics + Name : Diffusion Network + Behavior : Unknown + ----------------------------------------------------------------------------- + Period Adopters Cum Adopt. (%) Hazard Rate Density Moran's I (sd) + -------- ---------- ---------------- ------------- --------- ---------------- + 1 8 8 (0.08) - 0.50 -0.01 (0.00) + 2 3 11 (0.11) 0.03 0.50 -0.01 (0.00) + 3 6 17 (0.17) 0.07 0.51 -0.01 (0.00) + 4 3 20 (0.20) 0.04 0.49 -0.01 (0.00) + 5 9 29 (0.29) 0.11 0.50 -0.01 (0.00) + 6 5 34 (0.34) 0.07 0.50 -0.01 (0.00) + 7 2 36 (0.36) 0.03 0.51 -0.01 (0.00) + 8 3 39 (0.39) 0.05 0.50 -0.01 (0.00) + 9 5 44 (0.44) 0.08 0.50 -0.01 (0.00) + 10 1 45 (0.45) 0.02 0.49 -0.01 (0.00) + 11 3 48 (0.48) 0.05 0.50 -0.01 (0.00) + 12 6 54 (0.54) 0.12 0.50 -0.01 (0.00) + 13 8 62 (0.62) 0.17 0.50 -0.01 (0.00) + 14 9 71 (0.71) 0.24 0.50 -0.01 (0.00) + 15 5 76 (0.76) 0.17 0.50 -0.00 (0.00) ** + 16 7 83 (0.83) 0.29 0.50 -0.01 (0.00) + 17 5 88 (0.88) 0.29 0.49 -0.00 (0.00) *** + 18 4 92 (0.92) 0.33 0.50 -0.01 (0.00) + 19 1 93 (0.93) 0.12 0.50 -0.01 (0.00) + 20 2 95 (0.95) 0.29 0.50 -0.01 (0.00) + ----------------------------------------------------------------------------- + Left censoring : 0.08 (8) + Right centoring : 0.05 (5) + # of nodes : 100 + + Moran's I was computed on contemporaneous autocorrelation using 1/geodesic + values. Significane levels *** <= .01, ** <= .05, * <= .1. ``` r # Visualizing distribution of suscep/infect out <- plot_infectsuscep(diffnet, bins = 20,K=5, logscale = FALSE, h=.01) ``` -![](README_files/figure-gfm/plot_infectsuscept-1.png) +![](README_files/figure-commonmark/plot_infectsuscept-1.png) ``` r out <- plot_infectsuscep(diffnet, bins = 20,K=5, logscale = TRUE, exclude.zeros = TRUE, h=1) ``` - ## Warning in plot_infectsuscep.list(graph$graph, graph$toa, t0, normalize, : When - ## applying logscale some observations are missing. + Warning in plot_infectsuscep.list(graph$graph, graph$toa, t0, normalize, : When + applying logscale some observations are missing. -![](README_files/figure-gfm/plot_infectsuscept-2.png) +![](README_files/figure-commonmark/plot_infectsuscept-2.png) ### Threshold @@ -262,32 +245,26 @@ diffnet <- rdiffnet(500, 20, seed.nodes = "random", rgraph.args = list(m=3), threshold.dist = function(x) runif(1, .3, .7)) -``` - - ## Warning in (function (graph, p, algorithm = "endpoints", both.ends = FALSE, : - ## The option -copy.first- is set to TRUE. In this case, the first graph will be - ## treated as a baseline, and thus, networks after T=1 will be replaced with T-1. - -``` r diffnet ``` - ## Dynamic network of class -diffnet- - ## Name : A diffusion network - ## Behavior : Random contagion - ## # of nodes : 500 (1, 2, 3, 4, 5, 6, 7, 8, ...) - ## # of time periods : 20 (1 - 20) - ## Type : directed - ## Final prevalence : 1.00 - ## Static attributes : real_threshold (1) - ## Dynamic attributes : - + Dynamic network of class -diffnet- + Name : A diffusion network + Behavior : Random contagion + # of nodes : 500 (1, 2, 3, 4, 5, 6, 7, 8, ...) + # of time periods : 20 (1 - 20) + Type : directed + Num of behaviors : 1 + Final prevalence : 1.00 + Static attributes : real_threshold (1) + Dynamic attributes : - ``` r # Threshold with fixed vertex size plot_threshold(diffnet) ``` -![](README_files/figure-gfm/BoringThreshold,%20plot_threshold-1.png) +![](README_files/figure-commonmark/BoringThreshold,%20plot_threshold-1.png) Using more features @@ -303,10 +280,10 @@ plot_threshold( ) ``` - ## Warning in (function (graph, expo, toa, include_censored = FALSE, t0 = min(toa, - ## : -vertex.sides- will be coerced to integer. + Warning in (function (graph, expo, toa, include_censored = FALSE, t0 = min(toa, + : -vertex.sides- will be coerced to integer. -![](README_files/figure-gfm/NiceThreshold-1.png) +![](README_files/figure-commonmark/NiceThreshold-1.png) ### Adoption rate @@ -314,7 +291,7 @@ plot_threshold( plot_adopters(diffnet) ``` -![](README_files/figure-gfm/Adopters-1.png) +![](README_files/figure-commonmark/Adopters-1.png) ### Hazard rate @@ -322,7 +299,7 @@ plot_adopters(diffnet) hazard_rate(diffnet) ``` -![](README_files/figure-gfm/Hazard-1.png) +![](README_files/figure-commonmark/Hazard-1.png) ### Diffusion process @@ -330,14 +307,14 @@ hazard_rate(diffnet) plot_diffnet(medInnovationsDiffNet, slices=c(1,9,8)) ``` -![](README_files/figure-gfm/plot_diffnet-1.png) +![](README_files/figure-commonmark/plot_diffnet-1.png) ``` r diffnet.toa(brfarmersDiffNet)[brfarmersDiffNet$toa >= 1965] <- NA plot_diffnet2(brfarmersDiffNet, vertex.size = "indegree") ``` -![](README_files/figure-gfm/plot_diffnet2-1.png) +![](README_files/figure-commonmark/plot_diffnet2-1.png) ``` r set.seed(1231) @@ -367,7 +344,7 @@ mtext("Both networks have the same distribution on times of adoption", 1, outer = TRUE) ``` -![](README_files/figure-gfm/plot_diffnet2%20with%20map-1.png) +![](README_files/figure-commonmark/plot_diffnet2%20with%20map-1.png) ``` r par(oldpar) @@ -380,13 +357,13 @@ out <- classify(kfamilyDiffNet, include_censored = TRUE) ftable(out) ``` - ## thr Non-Adopters Very Low Thresh. Low Thresh. High Thresh. Very High Thresh. - ## toa - ## Non-Adopters 0.00 0.00 0.00 0.00 0.00 - ## Early Adopters 0.00 14.04 8.40 0.57 0.29 - ## Early Majority 0.00 5.64 11.65 5.54 2.58 - ## Late Majority 0.00 1.34 5.06 6.21 2.96 - ## Laggards 0.00 1.53 0.00 0.00 34.19 + thr Non-Adopters Very Low Thresh. Low Thresh. High Thresh. Very High Thresh. + toa + Non-Adopters 0.00 0.00 0.00 0.00 0.00 + Early Adopters 0.00 14.04 8.40 0.57 0.29 + Early Majority 0.00 5.64 11.65 5.54 2.58 + Late Majority 0.00 1.34 5.06 6.21 2.96 + Laggards 0.00 1.53 0.00 0.00 34.19 ``` r # Plotting @@ -400,7 +377,7 @@ legend("bottom", legend = levels(out$thr), fill=viridisLite::inferno(5), horiz = cex=.6, bty="n", inset=c(0,-.1)) ``` -![](README_files/figure-gfm/mosaic-1.png) +![](README_files/figure-commonmark/mosaic-1.png) ``` r par(oldpar) @@ -412,42 +389,41 @@ par(oldpar) sessionInfo() ``` - ## R version 4.4.1 (2024-06-14) - ## Platform: aarch64-apple-darwin23.4.0 - ## Running under: macOS Sonoma 14.6.1 - ## - ## Matrix products: default - ## BLAS: /opt/homebrew/Cellar/openblas/0.3.27/lib/libopenblasp-r0.3.27.dylib - ## LAPACK: /opt/homebrew/Cellar/r/4.4.1/lib/R/lib/libRlapack.dylib; LAPACK version 3.12.0 - ## - ## locale: - ## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8 - ## - ## time zone: America/Denver - ## tzcode source: internal - ## - ## attached base packages: - ## [1] stats graphics grDevices utils datasets methods base - ## - ## other attached packages: - ## [1] netdiffuseR_1.22.6 - ## - ## loaded via a namespace (and not attached): - ## [1] Matrix_1.7-0 highr_0.11 dplyr_1.1.4 - ## [4] compiler_4.4.1 tidyselect_1.2.1 Rcpp_1.0.12 - ## [7] networkLite_1.0.5 boot_1.3-30 yaml_2.3.8 - ## [10] fastmap_1.2.0 lattice_0.22-6 coda_0.19-4.1 - ## [13] R6_2.5.1 generics_0.1.3 MatchIt_4.5.5 - ## [16] igraph_2.0.3 knitr_1.47 MASS_7.3-60.2 - ## [19] backports_1.5.0 tibble_3.2.1 statnet.common_4.9.0 - ## [22] pillar_1.9.0 rlang_1.1.4 utf8_1.2.4 - ## [25] xfun_0.45 viridisLite_0.4.2 cli_3.6.3 - ## [28] magrittr_2.0.3 network_1.18.2 digest_0.6.36 - ## [31] grid_4.4.1 lifecycle_1.0.4 vctrs_0.6.5 - ## [34] sna_2.7-2 evaluate_0.24.0 SparseM_1.84-2 - ## [37] glue_1.7.0 fansi_1.0.6 rmarkdown_2.27 - ## [40] tools_4.4.1 pkgconfig_2.0.3 networkDynamic_0.11.4 - ## [43] htmltools_0.5.8.1 + R version 4.5.0 (2025-04-11) + Platform: aarch64-apple-darwin24.2.0 + Running under: macOS Sequoia 15.0.1 + + Matrix products: default + BLAS: /opt/homebrew/Cellar/openblas/0.3.29/lib/libopenblasp-r0.3.29.dylib + LAPACK: /opt/homebrew/Cellar/r/4.5.0/lib/R/lib/libRlapack.dylib; LAPACK version 3.12.1 + + locale: + [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8 + + time zone: America/Denver + tzcode source: internal + + attached base packages: + [1] stats graphics grDevices utils datasets methods base + + other attached packages: + [1] netdiffuseR_1.23.0 + + loaded via a namespace (and not attached): + [1] Matrix_1.7-3 jsonlite_2.0.0 dplyr_1.1.4 + [4] compiler_4.5.0 tidyselect_1.2.1 Rcpp_1.0.14 + [7] networkLite_1.1.0 boot_1.3-31 yaml_2.3.10 + [10] fastmap_1.2.0 lattice_0.22-6 coda_0.19-4.1 + [13] R6_2.6.1 generics_0.1.4 MatchIt_4.7.2 + [16] igraph_2.1.4.9046 knitr_1.50 MASS_7.3-65 + [19] backports_1.5.0 tibble_3.3.0 statnet.common_4.12.0 + [22] pillar_1.10.2 rlang_1.1.6 xfun_0.52 + [25] viridisLite_0.4.2 cli_3.6.5 magrittr_2.0.3 + [28] network_1.19.0 digest_0.6.37 grid_4.5.0 + [31] lifecycle_1.0.4 vctrs_0.6.5 sna_2.8 + [34] evaluate_1.0.3 SparseM_1.84-2 glue_1.8.0 + [37] rmarkdown_2.29 tools_4.5.0 pkgconfig_2.0.3 + [40] networkDynamic_0.11.5 htmltools_0.5.8.1 ## To-do list diff --git a/README.Rmd b/README.qmd similarity index 86% rename from README.Rmd rename to README.qmd index 0600f37..f279f82 100644 --- a/README.Rmd +++ b/README.qmd @@ -1,7 +1,5 @@ --- -output: - github_document: - html_preview: false +format: gfm --- [![R-CMD-check](https://github.com/USCCANA/netdiffuseR/actions/workflows/r.yml/badge.svg)](https://github.com/USCCANA/netdiffuseR/actions/workflows/r.yml) @@ -10,8 +8,8 @@ output: [![CRAN\_Status\_Badge](https://www.r-pkg.org/badges/version/netdiffuseR)](https://cran.r-project.org/package=netdiffuseR) [![](https://cranlogs.r-pkg.org/badges/grand-total/netdiffuseR)](https://cran.r-project.org/package=netdiffuseR) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1039317.svg)](https://doi.org/10.5281/zenodo.1039317) -[![Dependencies](https://tinyverse.netlify.com/badge/netdiffuseR)](https://cran.r-project.org/package=netdiffuseR) -[![USC's Department of Preventive Medicine](https://raw.githubusercontent.com/USCbiostats/badges/master/tommy-uscprevmed-badge.svg)](https://pphs.usc.edu/center/cana/) +[![Dependencies](https://tinyverse.netlify.app/badge/netdiffuseR)](https://cran.r-project.org/package=netdiffuseR) +[![USC's Department of Preventive Medicine](https://raw.githubusercontent.com/USCbiostats/badges/master/tommy-uscprevmed-badge.svg)](https://keck.usc.edu/cana/)

netdiffuseR: Analysis of Diffusion and Contagion Processes on Networks

@@ -20,7 +18,7 @@ This package contains functions useful for analyzing network data for diffusion The package was developed as part of the paper Thomas W. Valente, Stephanie R. Dyal, Kar-Hai Chu, Heather Wipfli, Kayo Fujimoto, *Diffusion of innovations theory applied to global tobacco control treaty ratification*, Social Science & Medicine, Volume 145, November 2015, Pages 89-97, ISSN 0277-9536 -(available [here](https://www.sciencedirect.com/science/article/pii/S027795361530143X)) +(available [here](https://doi.org/10.1016/j.socscimed.2015.10.001)). From the description: @@ -43,11 +41,6 @@ citation(package="netdiffuseR") Changelog can be view [here](NEWS.md). -* [2016-06-02] A video of the __netdiffuseR__ workshop at SUNBELT 2016 is now online on [youtube](https://www.youtube.com/playlist?list=PLT-GgRN1lFI4coHDqkRJm3flDw9e1gg2P), and the workshop materials can be found [here](https://github.com/USCCANA/netdiffuser-sunbelt2016/) -* [2016-04-11] __netdiffuseR__ will be on [useR! 2016](https://user2016.r-project.org/) on as a presentation and on [IC2S2 2016](https://www.kellogg.northwestern.edu/news-events/conference/ic2s2/2016.aspx) in the posters session. -* [2016-03-16] Next CRAN release scheduled for April 11th 2016 (after the workshop). -* [2016-02-18] __netdiffuseR__ vers 1.16.2 is now on CRAN! - ## Installation ### CRAN version @@ -60,10 +53,10 @@ install.packages("netdiffuseR") ### Bleeding edge version -If you want the latest (unstable) version of __netdiffuseR__, using the `devtools` package, you can install `netdiffuseR` dev version as follows +If you want the latest (unstable) version of __netdiffuseR__, using the `remotes` package, you can install `netdiffuseR` dev version as follows ```r -devtools::install_github('USCCANA/netdiffuseR', build_vignettes = TRUE) +remotes::install_github('USCCANA/netdiffuseR', build_vignettes = TRUE) ``` You can skip building vignettes by setting `build_vignettes = FALSE` (so it is not required). @@ -103,11 +96,7 @@ For the case of windows and mac users, they can find binary versions of the pack ## Tutorials -Since starting netdiffuseR, we have done a couple of workshops at Sunbelt and NASN. Here are the repositories: - -* Sunbelt 2018: https://usccana.github.io/netdiffuser-sunbelt2018/ ([source code](https://github.com/USCCANA/netdiffuser-sunbelt2018)) -* NASN 2017: https://usccana.github.io/netdiffuser-nasn2017/ ([source code](https://github.com/USCCANA/netdiffuser-nasn2017)) -* Sunbelt 2016: https://github.com/USCCANA/netdiffuser-sunbelt2016 +Since starting netdiffuseR, we have done a couple of workshops at Sunbelt and NASN. Past and current workshops can be found at ## Presentations diff --git a/inst/CITATION b/inst/CITATION index 768ed34..f22ff42 100644 --- a/inst/CITATION +++ b/inst/CITATION @@ -1,4 +1,4 @@ -year <- sub("-.*", "", meta$Date) +year <- 2025 note <- sprintf("R package version %s", meta$Version) bibentry( @@ -28,6 +28,7 @@ bibentry(bibtype = "Manual", title = "{{netdiffuseR: Analysis of Diffusion and Contagion Processes on Networks}}", author = c( person("George", "Vega Yon", comment = c(ORCID = "0000-0002-3171-0844")), + person("Anibal", "Olivera Morales", comment=c(ORCID="0009-0000-3736-7939", what="Multi-diffusion version")), person("Thomas", "Valente", comment=c(ORCID="0000-0002-8824-5816")) ), year = year, diff --git a/inst/NEWS b/inst/NEWS deleted file mode 100644 index 08edec7..0000000 --- a/inst/NEWS +++ /dev/null @@ -1,509 +0,0 @@ -Changes in netdiffuseR version 1.22.7 (2024-09-18) - -- Minor changes to testing (skip warnings). - -Changes in netdiffuseR version 1.22.5 (2022-11-30) - -- Adressing roxygen2 issue #1491 - -Changes in netdiffuseR version 1.22.5 (2022-11-30) - -- Solved warning and errors reported by CRAN before the package was - archived. - -- New S3 generic functions is_self, is_multiple, is_valued, and - is_undirected allow querying graph information for some methods. - -- Fixed bug in diag_expand. Graphs with self ties were not transformed - correctly (diagonals were excluded.) - -Changes in netdiffuseR version 1.22.4 (2022-09-16) - -- Replaced getMethod("t"...) by t responding to changes in the Matrix - package. - -Changes in netdiffuseR version 1.22.1 (2021-05-27) - -- netdiffuseR has now a logo! - -- Making updates after changes in knitr and Matrix. - -Changes in netdiffuseR version 1.22.0 (2020-05-17) - -- Fixing a new issue regarding structural equivalence calculation. In - the new version, the function has been fully ported to R, which - should avoid problems related to the C++ code. - -- As documented, struct_equiv now returns he euclidean distance matrix - (it was not doing that). - -Changes in netdiffuseR version 1.21.0 (2020-02-10) - -- Getting netdiffuseR back to CRAN. We have fixed issues that arise - from the next big CRAN release, in particular, matrices are now - arrays. That was creating issues throughout the package (now fixed). - -Changes in netdiffuseR version 1.20.2 (2019-03-25) - -- Repaired broken link in bootnet. - -Changes in netdiffuseR version 1.20.1 (2019-03-22) - -- This version has no user level visible changes. - -Other changes - -- Changing PI macros in C++ code as requested by RcppCore. - -- Setting 3.5 seed version for tests so that test won’t break - following message from CRAN. - -Changes in netdiffuseR version 1.20.0 (2018-06-06) - -New functions and features - -- diffreg provides a wrapper of glm to run lagged regression models. - -- Default colors for plot_diffnet2, plot_infectsucept, and others are - now selected from the viridis R package, which provides perceptually - uniform and colorblind proof colors. - -Bug fixes - -- plot_diffnet2 now has the correct scaling in nodes positions. - -- rdiffnet_multiple calls library(netdiffuseR) when using multicore. - -Other changes - -- arrow.width in plot_threshold.default now set to be equal to - nslices(graph)/80. - -- curved option passed to plot_._threshold.default. - -- The c++ function edges_arrow now returns two different elements (the - edge, and the arrow). - -Changes in netdiffuseR version 1.19.0 (2017-10-16) - -New functions and features - -- rdiffnet now allows passing scalars for threshold.dist, more over, - the user can also ask the function to just warn when there is no - diffusion instead of returning with error. - -- plot.diffnet, plot_diffnet, plot.diffnet_mentor, and plot_diffnet2 - use igraph for plotting. Also, users can now pass “degree” for - -vertex.size- (vertex.cex not used anymore), allowing to - “automatically” scale vertices by (in/out/.)degree. Also, plotting - arguments like vertex.* or edge.* are standarized so these match - igraph. - -- plot_diffnet has a new parameter: background. - -- rdiffnet_multiple, a wrapper of rdiffnet, allows performing - simulations studies by running simulating multiple diffusion - networks using rdiffnet. - -- exposure has a new parameter: lags. By default lags = 0, returns a - lagged exposure matrix. - -Bug fixes - -- igraph_to_diffnet was failing with the graph had no weights. - -- drop_isolated was not behaving well for diffnet objects. - -- vertex_covariate_dist was incorrectly specified. Only the default - p=2 were OK. Now fixed and the tests/ folder includes a tests on - this. - -- plot_diffnet2 was not passing color.ramp to drawColorKey. Now fixed. - -- plot.diffnet_mentor had a bug. Uncesary permutation of vertices was - done, but it actually had no visible effect. Similar problem was - corrected in diffnet_to_igraph, and other plot methods using igraph - for plotting. - -Other changes - -- Replacing some C++ functions by R functions in cases in which there - was no decrease in performance. - -- plot_diffnet function now has smaller margins, so looks more - appealing. - -- New examples in vignettes “netdiffuseR showcase: Medical - Innovations”, and “Simulating diffusion networks: Using the rdiffnet - function”. - -Changes in netdiffuseR version 1.18.1 (2017-07-22) - -New functions - -- network_to_diffnet, diffnet_to_network coercion between diffnet and - network objects. - -- networkDynamic_to_diffnet, diffnet_to_networkDynamc coercion between - diffnet and networkDynamic objects. - -New features - -- new_diffnet and as_diffnet now receive static networks as well. - -Bug fixes - -- diffnet_to_igraph was copying over a single adjacency matrix, which - did a difference in dynamic networks. - -- diffnet_to_igraph was not considering loops correctly. - -- In unexpected situations egonet_attrs was crashing. - -Changes in netdiffuseR version 1.18.0 (2017-07-16) - -New functions - -- bootnet implements network bootstrapping based on Snijders and - Borgatti (1999) - -- mentor_matching implements Valente and Davis (1999) Mentor matching - algorithm. including a plot method. - -- approx_geodesic an alternative to igraph::distances and - sna::geodist. computes geodesics up to a certain number of steps and - returns a sparse matrix. - -- matrix_compare Efficiently compares two sparse matrices looking only - at the valued cells. - -- as_dgCMatrix Coerce matrix-like objects into dgCMatrix objects - (sparse matrices from the Matrix package). - -- fitbass Fits the Bass Diffusion Model to an observed vector of - cumulative adopters. The estimation is done via stats::nls. - -- netmatch and netmatch_prepare (on development) implement matching - estimators with network data. - -Bugs Fixes - -- dgr returned with error when self == TRUE - -- In some calls to igraph::graph_from_adj... sorting of vertices was - not preserved. - -- The matrix method in egonet_attrs was passing a list of vertices - instead of the attributes. Fixed. - -- transformGraphBy was returning with error when the time periods - ranged other than 1, 2, … - -New Features - -- rgraph_er is now significantly faster (orders of magnitude compare - to previous versions). rgraph_ba is faster too. - -- moran now returns the sd, expected and p-value. - -- exposure now receives static graphs in alt.graph with a warning. - -- rewire_graph now also uses QAP. This affects directly to - structu_test. - -Changes in netdiffuseR version 1.17.0 (2016-11-10) - -New features and changes - -- The title of the package is now Analysis of Diffusion and Contagion - Processes on Networks. - -- The function struct_test now allows other types of graphs. Before it - only supported diffnet objects. - -- The function rewire_graph gains a new argument for the algorithm - “swap”. Now to ensure aperiodicity in MCMC a chance of skiping a - rewire has been included. - -- The function n_rewires now has a default of 20 (before it was 100). - This is based on Ray et al (2012) (more details in the manual). - -- The function rgraph_ba gains a new argument, self=TRUE. By default - behaves as before following Bollobas, but now can deviate to - generate graphs with no autolinks. - -- In rgraph_ba, the argument eta allows implementing De Almeida et - al. (2013) Scale-free homophilic networks. - -- The functions exposure and dgr are now pure R code (C++ functions - were replace since there were no significant speed gains). - -- diffnet class objects now have two new meta-values: name and - behavior. - -- Elements -graph-, -toa-, -adopt- and -cumadopt- in diffnet class - objects have lost their dimnames (more efficient storage). - -- classify_adopters now always includes Non-Adopters. - -New functions - -- vertex_covariate_dist computes distances between vertices using both - the graph and a matrix of length nxK. - -- vertex_mahalanobis_dist computes mahalanobis distance between - vertices (as above). - -- struct_test_asymp an asymptotic approximation of struct_test (not - recomended). - -- ego_variance computes a pseudo variance at the ego level (aux - function for struct_test). - -- transformGraphBy applies a function that transforms a graph - considering structural zeros given by groups. Similar to the idea of - the -by- option in struct_equiv. - -- read_ucinet read UCINET binary files (both header and graph file). - Still work in progress. - -- plot.diffnet_degSeq method allows visualizing degree sequence as - log-log plots (default). - -- diag_expand creates a single adjacency matrix from a dynamic graph. - -- summary.diffnet_adoptChange method generates a summary table of the - df generated by select_egoalter. - -- permute_graph permutes the values of an adjacency matrix - (Conditional Uniform Graph). - -- rewire_qap generates isomorphic graphs by “changing the labels”. - -Bug fixes - -- ^.diffnet method was rasing to +1 power, e.g. diffnet^2 was actually - diffnet^3. - -- /.diffnet was not working. - -- plot_diffnet was computing the coordinates of the cells wrongly. - Most of the time causing adding figures outside of the plotting - area. - -- The c.diffnet_struct_test method was not updating the p.value. - -- The function edgelist_to_adjmat was not processing correctly - undirected graphs when the edgelist represented a lower triangular - matrix. - -- The function survey_to_diffnet had an issue processin dyn graph - attrs returning errors. Now fixed. - -- The function select_egoalter returned error when graph was an array. - -- The method [[<-.diffnet failed when replacing a dynamic attribute - with a NULL value (e.g. dn[["my_dyn_att"]] <- NULL). - -Changes in netdiffuseR version 1.16.7 (2016-07-07) - -Bug fixes - -- Fixed bug in struct_equiv: When groupvar was a list (dynamic attr), - the function returned error. - -- Fixed bug in rewire_graph.array: Returned error when - algorithm="swap" - -- Fixed bug in rewire_graph: The option copy.first was not been - applied correctly. - -- In hist.diffnet_struct_test: ... now passed to hist.default. - -- Fixed bug on egonet_attrs: The matrix method was returning with - error. - -New features and changes - -- plot_infectsuscept includes 2D kernel smoother via MASS::kde2d. - -- infection, susceptibility and threshold now report NA for - non-adopters or excluded variables. - -- egonets_attrs now has new argument: self.attrs allows including - ego’s attributes as part of the outcome so it can be used by the - user. - -- plot_diffnet now uses igraph::plot.igraph for plotting instead - -- threshold gains a new argument: lags now users can define threshold - as exposure lags time periods prior to the time of adoption. By - default is 0 so its exposure at the time of adoption. - -New functions - -- New method c.diffnet_struct_test: A wrapper of boot:::c.boot. - -- diffusionMap computes the required matrix to be used with image-like - functions mapping a vertex covariate given a graph structure. - -- n_rewires: computes a suggested number of rewires per step in order - to attain unbiased graph samples. - -- diffnetLapply: Apply throught periods on diffnet objects. - -- Several new methods for the class diffnet. Now users can apply str, - dimnames (so colnames and rownames), t, &, |, dim and %*%. - -- drawColorKey: Handy function to draw a color key in the current - plot. - -- classify_adopters: As in Valente (1995), depending on time of - adoption, adopters are classified as early adopters, early majority, - late majority, and laggards. The function introduces a new class and - has methods for ftable and plot. - -- rescale_vertex_igraph: Helper function to fix the size of vertex - when calling plot.igraph so that the size is proportional to the - x-axis. - -Changes in netdiffuseR version 1.16.5 (2016-05-02) - -Bug fixes - -- Bug fixed on edgelist_to_adjmat: Counting number of vertices is now - done right after recode. (Reported by Tom) - -- Fixed bug in diffnet.attrs(..., as.df=TRUE). ids were wrongly - retrieved. - -- Fixed bugs for rgraph_ba_cpp: Degree of new vertices was not - changing apropiately. This only was an issue when m>1. - -- Fixed bugs for the as_diffnet method for arrays. - -- Fixed bugs in rewire_graph. Indexing of the jth component (when - rewiring) was not been made correctly (now it does). Also, when - rewiring, the new endpoints were truncated to n-1 (now fixed). - -- Fixed bugs for as_diffnet: When a dynamic graph was passed with - slices names different from the time periods, the slices names were - kept. Now these are replaced by meta$pers. - -New features and changes - -- Support for int64_t in RcppArmadillo now allows for creating/reading - adjacency matrices with more than 4 billion elements (big graphs). - -- In edgelist_to_adjmat use.incomplete has been replaced by - keep.isolated which makes more sense for naming. Incomplete cases on - times or weights are still ignored (as these cannot be processed by - the c++ ‘engine’). (Reported by Tom) - -- In edgelist_to_adjmat times has been replaced by t0 and t1. So now - the user can import graphs with spells. - -- Added new elements to the diffnet_struct_test class: p.value, t0, - mean_t, and R. All these were available before either to be computed - or retrieved from the boot list at the class. - -- New argument for threshold. Now, by default, threshold levels are - not computed for adopters in the first time period as this can be a - biased estimate. If the user wants to compute such, he/she can set - include_censored=TRUE. - -- Attributes in diffnet objects are now stored as data frames (instead - of matrices). This affects the function diffnet.attrs, and - egonet_attrs as these use attributes directly. (Requested by Tom) - -- New features for the rewire_graph function. In particular, p can now - be a vector of length T, so each slice can have different rewiring - prob., and the new option copy.first which allows to recycle the - first rewired slice (see details). - -- New features for the exposure function. When graph is of class - diffnet, the function accepts attrs equal to the name of some the - graph’s attributes. Also, alt.graph can be specified as se, which - will be replaced by the inverse of the structural equivalence. When - valued=FALSE the function will switch it to TRUE and warn the user. - -- New argument for struct_equiv and exposure, groupvar. This new - option provides a convenient way of calculating structural - equivalence and exposure clusterized by group. Specially useful when - there are different communities in a graph. See examples in the - manual. - -- as_diffnet now has an internal function, check_as_diffnet_attrs, to - check input attributes dimensions and coerce them into proper - class/structure. Valid attributes are now documented in the - function’s manual. - -- New arguments for edges_coords: dev and ran allow including device + - margins aspec ratio and plotting area y/x limits for improved aspect - ratio computation. - -- New internal function edges_arrow: Computes the coordinates of a 4 - points polygon allowing to draw pretty arrows considering aspec - ratio of device, margins and y/x. - -- Geodesic distances are now computed using igraph::distances instead - of sna::geodist as it is more flexible and faster. - -- New arguments for plot_threshold: vertex.sides, vertex.lab.cex, - vertex.lab.adj, vertex.lab.col, vertex.rot, jitter.factor, and - jitter.amount to give more control. - -- New internal function vertex_coords: Creates polygons of any given - number of sides considering aspec ratio of both x/y and device. - -- New features for rdiffnet. seed.graph can be either a function that - generates a random graph, a character string (as before) indicating - the class of graph to generate, or any other class of graph (either - static or dynamic) as specified in netdiffuseR-graphs. seed.nodes - can now be a vector with indices pointing to the initial adopters. - -- The rewiring algorithm for rgraph_ws has been replaced with a - rewire_ws which has been implemented as it was presented in Watts - and Strogatz (1998). - -New functions - -- New function: survey_to_diffnet. This function allows importing - network nomination data (in survey fashion) of both types, - cross-section and panel formats (static network only varying - adoption, or dynamic network varying attributes and network - structure simultaneously). - -- New function: edgelist_to_diffnet. Similar to survey_to_diffnet, - this function reads diffusion networks from an adjacency matrix and - a vertex attributes data frame. Both the attributes and the edgelist - can be static or dynamic. - -- New method: as.array.diffnet. - -- New functions: read_pajek and read_ucinet. Still on development. - -- New functions: nvertices and nedges return the number of vertices - and edges that a graph has. This can be applied to any class of - graph accepted by the package. - -- New indexing methods via [[.diffnet, [[<-.diffnet, for network - attributes and [.diffnet and [<-.diffnet for adjacency matrix. The - function diffnet.attrs<- will be deprecated for the next CRAN - release. The function diffnet.subset.slices is now not exported - (internal use), so the user needs to use the [.diffnet method - instead. - -- New concatenating method c.diffnet for diffnet objects. This method - allows ‘adding up’ diffnet objects. - -- New print method for diffnet_se, objects returned by struct_equiv. - -- New function diffnet_to_igraph. - -- New rewiring algorithm, rewire_swap implements the edge-switch - algorithm in an efficient way. This preserves degree sequences. - -Changes in netdiffuseR version 1.16.2 (2016-02-18) - -- First CRAN version. diff --git a/man/diffnet-class.Rd b/man/diffnet-class.Rd index 240ee15..f2532b4 100644 --- a/man/diffnet-class.Rd +++ b/man/diffnet-class.Rd @@ -52,7 +52,7 @@ new_diffnet( self = getOption("diffnet.self"), multiple = getOption("diffnet.multiple"), name = "Diffusion Network", - behavior = "Unspecified" + behavior = NULL ) \method{as.data.frame}{diffnet}( @@ -146,7 +146,7 @@ order of the rows in the attribute data.} \item{name}{Character scalar. Name of the diffusion network (descriptive).} -\item{behavior}{Character scalar. Name of the behavior been analyzed (innovation).} +\item{behavior}{Character vector. Name of the behavior(s) been analyzed (innovation).} \item{x}{A \code{diffnet} object.} @@ -195,7 +195,7 @@ throught time (dynamic).} \item \code{undirected}: Logical scalar. \item \code{multiple}: Logical scalar. \item \code{name}: Character scalar. - \item \code{behavior}: Character scalar. + \item \code{behavior}: A list of character scalars. } } } diff --git a/man/figures/netdiffuser-logo.png b/man/figures/netdiffuser-logo.png index cfa4751..0810233 100644 Binary files a/man/figures/netdiffuser-logo.png and b/man/figures/netdiffuser-logo.png differ diff --git a/man/netdiffuseR.Rd b/man/netdiffuseR.Rd index 4229cfc..ce516f5 100644 --- a/man/netdiffuseR.Rd +++ b/man/netdiffuseR.Rd @@ -25,13 +25,8 @@ netdiffuseR was created with the support of grant R01 CA157577 from the National \section{Workshops and Tutorials}{ -Online you can find several learning resources: - -\itemize{ -\item Sunbelt 2016 \url{https://github.com/USCCANA/netdiffuser-sunbelt2016} -\item NASN 2017 \url{https://github.com/USCCANA/netdiffuser-nasn2017} -\item Sunbelt 2018 \url{https://github.com/USCCANA/netdiffuser-sunbelt2018} -} +Online you can find several learning resources, particularly, at the +netdiffuseR workshop website: . } \author{ diff --git a/man/plot_threshold.Rd b/man/plot_threshold.Rd index 9900fdd..56b4566 100644 --- a/man/plot_threshold.Rd +++ b/man/plot_threshold.Rd @@ -7,7 +7,7 @@ \alias{plot_threshold.default} \title{Threshold levels through time} \usage{ -plot_threshold(graph, expo, vertex.label, ...) +plot_threshold(graph, expo, ...) \method{plot_threshold}{diffnet}(graph, expo, ...) @@ -56,8 +56,6 @@ plot_threshold(graph, expo, vertex.label, ...) \item{expo}{\eqn{n\times T}{n * T} matrix. Esposure to the innovation obtained from \code{\link{exposure}}} -\item{vertex.label}{Character vector of size \eqn{n}. Labels of the vertices.} - \item{...}{Additional arguments passed to \code{\link{plot}}.} \item{toa}{Integer vector of length \eqn{n} with the times of adoption.} @@ -83,6 +81,8 @@ plot_threshold(graph, expo, vertex.label, ...) \item{vertex.color}{Either a vector of size \eqn{n} or a scalar indicating colors of the vertices.} +\item{vertex.label}{Character vector of size \eqn{n}. Labels of the vertices.} + \item{vertex.label.pos}{Integer value to be passed to \code{\link{text}} via \code{pos}.} \item{vertex.label.cex}{Either a numeric scalar or vector of size \eqn{n}. Passed to \code{text}.} diff --git a/man/rdiffnet.Rd b/man/rdiffnet.Rd index fe4b2fa..0d63f7b 100644 --- a/man/rdiffnet.Rd +++ b/man/rdiffnet.Rd @@ -235,7 +235,10 @@ random_dis <- function(expo, cumadopt, time) { return(list_disadopt) } -diffnet_6 <- rdiffnet(seed.graph = graph, t = 10, disadopt = random_dis, seed.p.adopt = list(0.1, 0.1)) +diffnet_6 <- rdiffnet( + seed.graph = graph, t = 10, disadopt = random_dis, + seed.p.adopt = list(0.1, 0.1) +) # (Multiple simulations of single behavior): -------------------------------- # Simulation study comparing the diffusion with diff sets of seed nodes diff --git a/man/rewire_graph.Rd b/man/rewire_graph.Rd index 979bb13..8f7509d 100644 --- a/man/rewire_graph.Rd +++ b/man/rewire_graph.Rd @@ -14,7 +14,8 @@ rewire_graph( undirected = getOption("diffnet.undirected"), pr.change = ifelse(self, 0.5, 1), copy.first = TRUE, - althexagons = FALSE + althexagons = FALSE, + warn = TRUE ) } \arguments{ @@ -39,7 +40,10 @@ or an integer vector with number of iterations (\code{algorithm="swap"}).} \item{copy.first}{Logical scalar. When \code{TRUE} and \code{graph} is dynamic uses the first slice as a baseline for the rest of slices (see details).} -\item{althexagons}{Logical scalar. When \code{TRUE} uses the compact alternating +\item{althexagons}{Logical scalar. When \code{TRUE} uses the compact alternating} + +\item{warn}{Logical scalar. If \code{TRUE} (default) shows warnings when +recycling the first slice in dynamic graphs. hexagons algorithm (currently ignored [on development]).} } \value{ diff --git a/man/rgraph_ba.Rd b/man/rgraph_ba.Rd index dad8239..ad84bd2 100644 --- a/man/rgraph_ba.Rd +++ b/man/rgraph_ba.Rd @@ -96,7 +96,7 @@ Albert-László Barabási, & Albert, R. (1999). Emergence of Scaling in Random Networks. Science, 286(5439), 509–512. \doi{10.1126/science.286.5439.509} Albert-László Barabási. (2016). Network Science: (1st ed.). Cambridge University Press. -Retrieved from \url{https://barabasi.com/book/network-science} +Retrieved from \url{https://networksciencebook.com} De Almeida, M. L., Mendes, G. A., Madras Viswanathan, G., & Da Silva, L. R. (2013). Scale-free homophilic network. European Physical Journal B, 86(2). diff --git a/man/rgraph_er.Rd b/man/rgraph_er.Rd index eaa3b3b..94195b2 100644 --- a/man/rgraph_er.Rd +++ b/man/rgraph_er.Rd @@ -71,7 +71,7 @@ rgraph_er(t=5) } \references{ Barabasi, Albert-Laszlo. "Network science book" Retrieved November 1 (2015) -\url{https://barabasi.com/book/network-science}. +\url{https://networksciencebook.com}. } \seealso{ Other simulation functions: diff --git a/man/split_behaviors.Rd b/man/split_behaviors.Rd new file mode 100644 index 0000000..a80bbe4 --- /dev/null +++ b/man/split_behaviors.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/rdiffnet.r +\name{split_behaviors} +\alias{split_behaviors} +\title{Splitting behaviors} +\usage{ +split_behaviors(diffnet_obj) +} +\arguments{ +\item{diffnet_obj}{A multi-diffusion diffnet object.} +} +\value{ +A list of diffnet objects. Each element represent a unique behavior. +} +\description{ +Split each behavior within multi-diffusion diffnet object. The function gets +\code{toa}, \code{adopt}, \code{cumadopt}, and the \code{behavior} name from +each behavior, and returns a list where each element is a single behavior. +All the rest of the structure remains the same for each element in the list. +} +\examples{ +# Running a multi-diffusion simulation +set.seed(1231) +diffnet_multi <- rdiffnet(50, 5, seed.p.adopt = list(0.1,0.1)) + +diffnet_multi_list <- split_behaviors(diffnet_multi) +diffnet_single <- diffnet_multi_list[[1]] + +# You can now run standard functions for a single behavior +# Plotting single behavior +plot_diffnet(diffnet_single, slices = c(1, 3, 5)) + +} +\author{ +George G. Vega Yon & Aníbal Olivera M. +} diff --git a/netdiffuseR.Rproj b/netdiffuseR.Rproj index dd8cb83..8de93d9 100755 --- a/netdiffuseR.Rproj +++ b/netdiffuseR.Rproj @@ -1,4 +1,5 @@ Version: 1.0 +ProjectId: cd097d00-46b5-4411-bf0c-2d01da946aea RestoreWorkspace: No SaveWorkspace: No diff --git a/src/plot.cpp b/src/plot.cpp index 0a9ee8f..7c916cd 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -217,6 +217,14 @@ NumericMatrix edges_coords( LogicalVector curved = LogicalVector::create() ) { + // Checking sizes of x, toa, y, and vertex_cex + int n = x.n_rows; + if (n != y.n_rows) stop("-x- and -y- lengths do not coincide."); + if (n != toa.n_rows) stop("-x- and -toa- lengths do not coincide."); + if (n != vertex_cex.n_rows) stop("-x- and -vertex_cex- lengths do not coincide."); + if (graph.n_rows != graph.n_cols) stop("-graph- is not a square matrix."); + if (graph.n_rows != n) stop("-graph- does not have the same number of rows as -x-, -y-, and -toa-."); + // The output matrix has the following // - x0 and y0 // - x1 and y1 diff --git a/tests/testthat/test-rdiffnet.R b/tests/testthat/test-rdiffnet.R index b810e37..75c070f 100644 --- a/tests/testthat/test-rdiffnet.R +++ b/tests/testthat/test-rdiffnet.R @@ -200,7 +200,10 @@ test_that("Disadoption works", { } - ans_d_adopt <- rdiffnet(n = n, t = 10, disadopt = d_adopt, seed.p.adopt = list(0.1, 0.1)) + ans_d_adopt <- rdiffnet( + n = n, t = 10, disadopt = d_adopt, + seed.p.adopt = list(0.1, 0.1) + ) tmat <- toa_mat(ans_d_adopt) should_be_ones_or_zeros <- tmat[[1]]$cumadopt[, 10] + tmat[[2]]$cumadopt[, 10] diff --git a/vignettes/large-simulation.Rmd b/vignettes/large-simulation.Rmd deleted file mode 100644 index 7b811c4..0000000 --- a/vignettes/large-simulation.Rmd +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Vignette Title" -author: "Vignette Author" -date: "`r Sys.Date()`" -output: rmarkdown::html_vignette -vignette: > - %\VignetteIndexEntry{Vignette Title} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r setup, include = FALSE} -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>" -) -``` - -# Preliminaries - -We are interested in running a large scale simulation featuring hundreds of thousands (if not millions) of vertices. Before we proceed, you need to consider the following: - -1. Networks in netdiffuseR are sparse-matrices, thus, as long as the network is sparsely connected, it will fit in a regular computer. -2. At the same time, converting a sparse-matrix into a dense matrix at this scale **is not a good idea**, as you computer may crash. This would be the case, for example, if you want to calculate the geodesic matrix. -3. Following the previous point, using `summary(..., skip.moran = FALSE)`--the default behavior--is not a good idea. When dealing with large graphs, set `skip.moran = TRUE` to avoid memory overflow. - -# Case 1: Single simulation - -Suppose we want to simulate a diffusion process with the following parameters: - -- Network type: Small world with parameters $n=200k, k = 10, p = .1$ - -```{r setp-1, eval=FALSE} -library(netdiffuseR) -``` - -We no proceed with the simulation - -```{r sim-1, eval=FALSE} -ans_sw <- rdiffnet(n = 200, t = 10) -``` - - - diff --git a/vignettes/simulating-multiple-behaviors-on-networks.Rmd b/vignettes/simulating-multiple-behaviors-on-networks.Rmd index ca65c5f..f7bc176 100644 --- a/vignettes/simulating-multiple-behaviors-on-networks.Rmd +++ b/vignettes/simulating-multiple-behaviors-on-networks.Rmd @@ -2,7 +2,11 @@ title: "Simulating Multiple Behaviors on Networks" author: "Aníbal Olivera M." date: "2024-11-21" -output: html_document +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Simulating Multiple Behaviors on Networks} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} --- \tableofcontents