Simulates a diffusion network by creating a random dynamic network and
adoption threshold levels. You can perform a simulation for a single behavior
(using seed.p.adopt of class numeric in rdiffnet),
conduct multiple simulations for a single behavior (with rdiffnet_multiple),
or run a simulation with multiple behaviors simultaneously (using seed.p.adopt
of class list in rdiffnet)
rdiffnet_multiple(R, statistic, ..., ncpus = 1L, cl = NULL)
rdiffnet(
n,
t,
seed.nodes = "random",
seed.p.adopt = 0.05,
seed.graph = "scale-free",
rgraph.args = list(),
rewire = TRUE,
rewire.args = list(),
threshold.dist = runif(n),
exposure.args = list(),
name = "A diffusion network",
behavior = "Random contagion",
stop.no.diff = TRUE,
disadopt = NULL
)Integer scalar. Number of simulations to be done.
A Function to be applied to each simulated diffusion network.
Further arguments to be passed to rdiffnet.
Integer scalar. Number of processors to be used (see details).
An object of class c("SOCKcluster", "cluster")
(see details).
Integer scalar. Number of vertices.
Integer scalar. Time length.
Either a character scalar, a vector or a list (multiple behaviors only). Type of seed nodes (see details).
Numeric scalar or a list (multiple behaviors only). Proportion of early adopters.
Baseline graph used for the simulation (see details).
List. Arguments to be passed to rgraph.
Logical scalar. When TRUE, network slices are generated by rewiring
(see rewire_graph).
List. Arguments to be passed to rewire_graph.
For a single behavior diffusion, either a function to be applied via sapply,
a numeric scalar, or a vector/matrix with \(n\) elements. For \(Q\) behavior diffusion,
it can also be an \(n \times Q\) matrix or a list of \(Q\) single behavior inputs. Sets the adoption
threshold for each node.
List. Arguments to be passed to exposure.
Character scalar. Passed to as_diffnet.
Character scalar or a list or character scalar (multiple behaviors only). Passed to as_diffnet.
Logical scalar. When TRUE, the function will return
with error if there was no diffusion. Otherwise it throws a warning.
Function of disadoption, with current exposition, cumulative adoption, and time as possible inputs.
A random diffnet class object.
rdiffnet_multiple returns either a vector or an array depending
on what statistic is (see sapply and
parSapply).
Instead of randomizing whether an individual adopts the innovation or not, this toy model randomizes threshold levels, seed adopters and network structure, so an individual adopts the innovation in time \(T\) iff his exposure is above or equal to his threshold. The simulation is done in the following steps:
Using seed.graph, a baseline graph is created.
Given the baseline graph, the set of initial adopters is defined
using seed.nodes.
Afterwards, if rewire=TRUE, \(t-1\) slices of the network are created
by iteratively rewiring the baseline graph.
The threshold.dist function is applied to each node in the graph.
Simulation starts at \(t=2\) assigning adopters in each time period accordingly to each vertex's threshold and exposure.
When seed.nodes is a character scalar it can be "marginal", "central" or "random",
so each of these values sets the initial adopters using the vertices with lowest
degree, with highest degree or completely randomly.
For a single behavior diffusion, the number of early adopters is set as seed.p.adopt * n.
To run multiple behavior diffusion, seed.p.adopt must be a list (see examples below).
Please note that when marginal nodes are
set as seed it may be the case that no diffusion process is attained as the
chosen set of first adopters can be isolated. Any other case will be considered
as an index (via [<- methods), hence the user can manually set the set of initial adopters, for example
if the user sets seed.nodes=c(1, 4, 7) then nodes 1, 4 and 7 will be
selected as initial adopters.
The argument seed.graph can be either a function that generates a graph
(Any class of accepted graph format (see netdiffuseR-graphs)), a
graph itself or a character scalar in which the user sets the algorithm used to
generate the first network (network in t=1), this can be either "scale-free"
(Barabasi-Albert model using the rgraph_ba function, the default),
"bernoulli" (Erdos-Renyi model using the rgraph_er function),
or "small-world" (Watts-Strogatz model using the rgraph_ws
function). The list rgraph.args passes arguments to the chosen algorithm.
When rewire=TRUE, the networks that follow t=1 will be generated using the
rewire_graph function as \(G(t) = R(G(t-1))\), where \(R\)
is the rewiring algorithm.
If a function, the argument threshold.dist sets the threshold for each vertex in the graph.
It is applied using sapply as follows
sapply(1:n, threshold.dist)By default sets the threshold to be random for each node in the graph.
If seed.graph is provided, no random graph is generated and the simulation
is applied using that graph instead.
rewire.args has the following default options:
p | .1 |
undirected | getOption("diffnet.undirected", FALSE) |
self | getOption("diffnet.self", FALSE) |
exposure.args has the following default options:
outgoing | TRUE |
valued | getOption("diffnet.valued", FALSE) |
normalized | TRUE |
The function rdiffnet_multiple is a wrapper of rdiffnet wich allows
simulating multiple diffusion networks with the same parameters and apply
the same function to all of them. This function is designed to allow the user
to perform larger simulation studies in which the distribution of a particular
statistic is observed.
When cl is provided, then simulations are done via
parSapply. If ncpus is greater than
1, then the function creates a cluster via makeCluster
which is stopped (removed) once the process is complete.
Other simulation functions:
permute_graph(),
rewire_graph(),
rgraph_ba(),
rgraph_er(),
rgraph_ws(),
ring_lattice()
# (Single behavior): --------------------------------------------------------
# A simple example
set.seed(123)
diffnet_1 <- rdiffnet(100,10)
diffnet_1
#> Dynamic network of class -diffnet-
#> Name : A diffusion network
#> Behavior : Random contagion
#> # of nodes : 100 (1, 2, 3, 4, 5, 6, 7, 8, ...)
#> # of time periods : 10 (1 - 10)
#> Type : directed
#> Num of behaviors : 1
#> Final prevalence : 0.23
#> Static attributes : real_threshold (1)
#> Dynamic attributes : -
summary(diffnet_1)
#> Diffusion network summary statistics
#> Name : A diffusion network
#> Behavior : Random contagion
#> -----------------------------------------------------------------------------
#> Period Adopters Cum Adopt. (%) Hazard Rate Density Moran's I (sd)
#> -------- ---------- ---------------- ------------- --------- ----------------
#> 1 5 5 (0.05) - 0.01 -0.02 (0.06)
#> 2 1 6 (0.06) 0.01 0.01 0.09 (0.07)
#> 3 3 9 (0.09) 0.03 0.01 0.32 (0.07) ***
#> 4 2 11 (0.11) 0.02 0.01 0.36 (0.06) ***
#> 5 0 11 (0.11) 0.00 0.01 0.16 (0.07) **
#> 6 3 14 (0.14) 0.03 0.01 0.43 (0.06) ***
#> 7 2 16 (0.16) 0.02 0.01 0.16 (0.06) ***
#> 8 1 17 (0.17) 0.01 0.01 0.14 (0.07) **
#> 9 3 20 (0.20) 0.04 0.01 0.26 (0.07) ***
#> 10 3 23 (0.23) 0.04 0.01 0.36 (0.07) ***
#> -----------------------------------------------------------------------------
#> Left censoring : 0.05 (5)
#> Right centoring : 0.77 (77)
#> # of nodes : 100
#>
#> Moran's I was computed on contemporaneous autocorrelation using 1/geodesic
#> values. Significane levels *** <= .01, ** <= .05, * <= .1.
# Adopt if at least two neighbors have adopted ------
n <- 100; t <- 5;
graph <- rgraph_ws(n, t, p=.3)
diffnet_2 <- rdiffnet(seed.graph = graph, t = t, threshold.dist=function(x) 2,
exposure.args=list(valued=FALSE, normalized=FALSE))
# Re thinking the Adoption of Tetracycline ----------
newMI <- rdiffnet(seed.graph = medInnovationsDiffNet$graph,
threshold.dist = threshold(medInnovationsDiffNet), rewire=FALSE)
# (Multiple behavior): ------------------------------------------------------
# A simple example
set.seed(123)
diffnet_3 <- rdiffnet(100, 10, seed.p.adopt = list(0.1, 0.15))
#> Message: Multi-diffusion behavior simulation selected. Number of behaviors: 2
#> Message: Object -seed.nodes- converted to a -list-.All behaviors will have the same -random- seed nodes.
#> Message: Name of 1 behavior provided, but 2 are needed. Names generalized to 'behavior'_1, 'behavior'_2, etc.
#> Warning: Coercing -toa- into integer.
diffnet_3
#> Dynamic network of class -diffnet-
#> Name : A diffusion network
#> Behavior : Random contagion_1, Random contagion_2
#> # of nodes : 100 (1, 2, 3, 4, 5, 6, 7, 8, ...)
#> # of time periods : 10 (1 - 10)
#> Type : directed
#> Num of behaviors : 2
#> Prevalence : 0.39, 0.64
#> Static attributes : real_threshold.1, real_threshold.2 (2)
#> Dynamic attributes : -
summary(diffnet_3)
#> Diffusion network summary statistics
#> Name : A diffusion network
#>
#> Behavior : Random contagion_1
#> -----------------------------------------------------------------------------
#> Period Adopters Cum Adopt. (%) Hazard Rate Density Moran's I (sd)
#> -------- ---------- ---------------- ------------- --------- ----------------
#> 1 10 10 (0.10) - 0.01 0.00 (0.07)
#> 2 6 16 (0.16) 0.07 0.01 0.23 (0.07) ***
#> 3 4 20 (0.20) 0.05 0.01 0.33 (0.07) ***
#> 4 2 22 (0.22) 0.03 0.01 0.34 (0.07) ***
#> 5 1 23 (0.23) 0.01 0.01 0.21 (0.07) ***
#> 6 5 28 (0.28) 0.06 0.01 0.36 (0.06) ***
#> 7 2 30 (0.30) 0.03 0.01 0.25 (0.06) ***
#> 8 2 32 (0.32) 0.03 0.01 0.28 (0.07) ***
#> 9 4 36 (0.36) 0.06 0.01 0.35 (0.07) ***
#> 10 3 39 (0.39) 0.05 0.01 0.39 (0.07) ***
#> -----------------------------------------------------------------------------
#> Left censoring : 0.15 (10)
#> Right centoring : 0.36 (61)
#>
#> Behavior : Random contagion_2
#> -----------------------------------------------------------------------------
#> Period Adopters Cum Adopt. (%) Hazard Rate Density Moran's I (sd)
#> -------- ---------- ---------------- ------------- --------- ----------------
#> 1 15 15 (0.15) - 0.01 0.01 (0.07)
#> 2 8 23 (0.23) 0.09 0.01 0.19 (0.07) ***
#> 3 2 25 (0.25) 0.03 0.01 0.31 (0.07) ***
#> 4 4 29 (0.29) 0.05 0.01 0.27 (0.07) ***
#> 5 5 34 (0.34) 0.07 0.01 0.36 (0.07) ***
#> 6 4 38 (0.38) 0.06 0.01 0.28 (0.06) ***
#> 7 7 45 (0.45) 0.11 0.01 0.44 (0.06) ***
#> 8 9 54 (0.54) 0.16 0.01 0.48 (0.07) ***
#> 9 4 58 (0.58) 0.09 0.01 0.51 (0.07) ***
#> 10 6 64 (0.64) 0.14 0.01 0.52 (0.07) ***
#> -----------------------------------------------------------------------------
#> Left censoring : 0.15 (15)
#> Right centoring : 0.36 (36)
#> # of nodes : 100
#>
#> Moran's I was computed on contemporaneous autocorrelation using 1/geodesic
#> values. Significane levels *** <= .01, ** <= .05, * <= .1.
# Fully specified multi-behavior example ------------
threshold_matrix <- matrix(runif(n * 2), nrow = n, ncol = 2)
seed_nodes <- sample(1:100, 10, replace = FALSE)
diffnet_4 <- rdiffnet(100, 10, seed.p.adopt = list(0, 0),
seed.nodes = list(seed_nodes, seed_nodes),
threshold.dist = threshold_matrix,
behavior = c("tobacco", "alcohol"))
#> Message: Multi-diffusion behavior simulation selected. Number of behaviors: 2
#> Warning: Set of initial adopters for behavior 1 set to 1.
#> Warning: Set of initial adopters for behavior 2 set to 1.
#> Warning: Coercing -toa- into integer.
diffnet_4
#> Dynamic network of class -diffnet-
#> Name : A diffusion network
#> Behavior : tobacco, alcohol
#> # of nodes : 100 (1, 2, 3, 4, 5, 6, 7, 8, ...)
#> # of time periods : 10 (1 - 10)
#> Type : directed
#> Num of behaviors : 2
#> Prevalence : 0.98, 0.98
#> Static attributes : real_threshold.1, real_threshold.2 (2)
#> Dynamic attributes : -
# Adopt if at least one neighbor has adopted the first behavior,
# and at least two neighbors have adopted the second behavior. ---
diffnet_5 <- rdiffnet(seed.graph = graph, t = t, seed.p.adopt = list(0.1, 0.1),
threshold.dist = list(function(x) 2, function(x) 2),
exposure.args=list(valued=FALSE, normalized=FALSE))
#> Message: Multi-diffusion behavior simulation selected. Number of behaviors: 2
#> Message: Object -seed.nodes- converted to a -list-.All behaviors will have the same -random- seed nodes.
#> Message: Name of 1 behavior provided, but 2 are needed. Names generalized to 'behavior'_1, 'behavior'_2, etc.
#> Warning: Coercing -toa- into integer.
diffnet_5
#> Dynamic network of class -diffnet-
#> Name : A diffusion network
#> Behavior : Random contagion_1, Random contagion_2
#> # of nodes : 100 (1, 2, 3, 4, 5, 6, 7, 8, ...)
#> # of time periods : 5 (1 - 5)
#> Type : directed
#> Num of behaviors : 2
#> Prevalence : 0.29, 0.39
#> Static attributes : real_threshold.1, real_threshold.2 (2)
#> Dynamic attributes : -
# With a disadoption function -----------------------
set.seed(1231)
random_dis <- function(expo, cumadopt, time) {
num_of_behaviors <- dim(cumadopt)[3]
list_disadopt <- list()
for (q in 1:num_of_behaviors) {
adopters <- which(cumadopt[, time, q, drop=FALSE] == 1)
if (length(adopters) == 0) {
# only disadopt those behaviors with adopters
list_disadopt[[q]] <- integer()
} else {
# selecting 10% of adopters to disadopt
list_disadopt[[q]] <- sample(adopters, ceiling(0.10 * length(adopters)))
}
}
return(list_disadopt)
}
diffnet_6 <- rdiffnet(
seed.graph = graph, t = 10, disadopt = random_dis,
seed.p.adopt = list(0.1, 0.1)
)
#> Message: Multi-diffusion behavior simulation selected. Number of behaviors: 2
#> Message: Object -seed.nodes- converted to a -list-.All behaviors will have the same -random- seed nodes.
#> Message: Name of 1 behavior provided, but 2 are needed. Names generalized to 'behavior'_1, 'behavior'_2, etc.
#> Warning: Coercing -toa- into integer.
# (Multiple simulations of single behavior): --------------------------------
# Simulation study comparing the diffusion with diff sets of seed nodes
# Random seed nodes
set.seed(1)
ans0 <- rdiffnet_multiple(R=50, statistic=function(x) sum(!is.na(x$toa)),
n = 100, t = 4, seed.nodes = "random", stop.no.diff=FALSE)
#> Warning: No diffusion for behavior 1 in this network.
# Central seed nodes
set.seed(1)
ans1 <- rdiffnet_multiple(R=50, statistic=function(x) sum(!is.na(x$toa)),
n = 100, t = 4, seed.nodes = "central", stop.no.diff=FALSE)
boxplot(cbind(Random = ans0, Central = ans1), main="Number of adopters")