-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathSocDistNets.Rmd
545 lines (359 loc) · 29.1 KB
/
SocDistNets.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
---
title: "**Can't I *please* just visit one friend?**"
subtitle: <font size="6"> Visualizing social distancing networks in the era of COVID-19 </font>
author: <font size="3" color="606060"> *Goodreau SM, Pollock ED, Birnbaum JK, Hamilton DT, Morris M, on behalf of the UW Network Modeling Group* </font>
date: "4/3/2020"
output:
html_document:
highlight: kate
theme: lumen
toc: yes
toc_float: true
number_sections: true
fig_width: 7
fig_height: 4
fig_caption: true
df_print: paged
code_folding: hide
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
# Install if you need these
#install.packages("flexdashboard")
#install.packages("statnet")
#install.packages("sna")
library(statnet)
library(sna)
```
# Important context
This website was initially created in late March of 2020, during the rapid expansion of the first wave of COVID-19 in the United States. It reflects that context, a time when there was an urgent need everywhere to either "flatten the curve" or keep it from rising in the first place. Stay-at-home orders and social distancing rules were in place nearly universally throughout the U.S. and many other countries in the world, even as folks were struggling with following them.
The epidemic continues to unfold. Most settings have now brought their incidence down considerably, and have relaxed social distancing rules. Seasonal cycles of infection are beginning to be established. At the same time, the virus continues to evolve, so the possibility of another large outbreak remains quietly in the background.
All of this means that the exact trade-offs involved in visiting a friend as you are reading this vary by location, context and time. However, the basic idea found in this webpage remains universal - once a virus like COVID is circulating, even if every household pulls back to allow only a very small number of face-to-face connections to other households, these few connections can still establish the potential for spread to a large fraction of the population.
Given all this, we will be keeping the remainder of the content of the webpage as is--but will periodically update this introduction to keep it tracking the broad context.
# The situation
COVID-19 is raging around the world, and you and your family have been asked (OK, told) to stay home and practice social distancing.
For the most part you are doing so, because you are good people.
But, you wonder---or perhaps, more likely, your kids wonder---**is there really so much harm in meeting up with just one friend?**
After all, there are all kinds of interactions still happening---between health care workers and patients, people in the food services industries and their customers, and so on. Why does one more matter?
This is a question we've heard a lot from our own friends and relatives.
**To be clear, when we talk about "meeting up" here, we mean doing so in a way that doesn't carefully follow all the rules about social distancing.** That is, you interact directly or at a distance of less than 6 feet, and/or you share various items between you without rigorous handwashing and disinfecting.
For many of the people asking the question, it seems particularly low-risk to meet up with a friend if neither one has an elderly person in their household, or someone else with a compromised immune system, given how concentrated the mortality is within those populations.
As network epidemiologists, this is our effort to explain why these connections matter more than they may seem.
<br>
<br>
# The Good Ol' Days {.tabset .tabset-pills .tabset-fade}
Let's start by imagining back to the good old days before COVID-19. People had lots of daily interactions with others outside their household. Let's say, for the sake of the example, that a community had 200 households, and the members of a typical household together created 15 regular interactions with other households.
**What would that look like?** We can visualize a network as a set of nodes and links. Here we'll make one in which the **nodes (green dots) represent households**, and the **links (gray lines) represent interactions** between members of two households.
[For those who want more detail---on terms, explanations and numbers---click on the "What's Going On"? button in each section; if you just want to compare the pictures, continue on!]
## The Network
```{r pre-COVID, cache=TRUE, echo=FALSE, warning=FALSE, error=FALSE, message=FALSE, fig.height=4, fig.width=4, fig.align='center'}
set.seed(0)
n <- 200
emptynet <- network.initialize(n, directed=FALSE)
meandeg.precov <- 15
fit.precov <- ergm(emptynet~edges,
target.stats=meandeg.precov*n/2)
net.precov <- simulate(fit.precov)
par(mai=c(0,0,0,0))
plot(net.precov, vertex.cex=1.5, mode="kamadakawai",
vertex.col=3, edge.col="gray20")
largcomp.precov <- sum(component.largest(net.precov))
kpath.precov <- sna:::kpath.census(net.precov)$path.count[3,'Agg']/2
```
**The connections among the nodes are so numerous that you can't even make sense of them---it's all just a single dense mass of ties. For a new virus that is able to spread across those ties, and to which everyone is susceptible, life is pretty good.**
<br>
<br>
## What's going on?
The exact numbers we've chosen here, like 200 households and 15 ties each, don't matter much---we just want to imagine a world that is much more connected than it is under social distancing.
Let's put a few numbers on what you see here for comparison to later scenarios:
- One important feature of a network that helps us to understand how far something might spread on it is the size of the **"largest cluster"**. That refers to the largest set of households who are all **reachable** to one another along any possible path---that is, there is at least one path of any length that connects the two households.
- In this network, every household can be reached from every other household along at least one path---indeed, along many different ones---so the **largest cluster includes all 200 households---that is, 100% of households**.
- Another way of looking at connectivity is to count how many households are reachable along a path of a certain length. You've probably heard of the concept of "six degrees of separation"---that's someone who is your friend's friend's friend's friend's friend's friend. We will use that concept here.
- We'll look at each household, and measure on average how many other households are within **3 degrees of separation** from them, and also how many are within **6 degrees of separation**. We use these two numbers because they help us understand how much connectivity there is at different scales.
- **3 degrees of separation** represents someone you might have some sense of---someone in a household connected to a household connected to a household connected to you. Someone at that distance has a pretty good chance of transmitting COVID to you (if they're infected) or you to them (if you're infected). And with COVID-19, that could all happen before you have any symptoms and know that you're infected!
- **And 6 degrees of separation** is, of course, a very popular concept, and one that tells you about people who are far enough away on a chain that you probably know nothing about them. And yet there is a chance that they could be the source of a transmission chain that leads to you---or you could be the source of a transmission chain that leads to them.
```{r, cache=TRUE, echo=FALSE, warning=FALSE, error=FALSE, message=FALSE}
# Function to calculate geodesic summaries
geo.sep <- function(net, netname, distances=c(3,6)) {
# Geodesic matrix - if not reachable, use NA
geo.mat <- sna:::geodist(net, inf.replace=NA)$gdist
# How many households are separated by distance x or less?
# Do a node-based, not dyad-based, mean
means <- sapply(distances, function(x) {
geo.count <- (geo.mat<=x)
# geo.count[lower.tri(geo.count, diag=TRUE)] <- NA
diag(geo.count) <- NA
return(mean(colSums(geo.count, na.rm=TRUE)))
})
# Compute reachable nodes
#reachable <- geo.mat
#diag(reachable) <- NA
#num.reachable <- colSums(!is.na(reachable))
#print(summary(num.non.isolates))
#avg.reachable <- mean(num.reachable)
# Combine distances counts with reachable count
#means <- c(means, avg.reachable)
#names(means) <- c(distances, 'avg.reachable')
return(means)
}
```
```{r, cache=TRUE, echo=FALSE, warning=FALSE, error=FALSE, message=FALSE}
geo.precov <- geo.sep(net.precov)
```
In this pre-COVID network, the average household has **`r geo.precov[1]` other houses within 3 degrees of separation**. That means the entire community! This makes sense, because, with only 200 households, it is a small, and tight-knit place. And of course, that means that all **`r geo.precov[2]` other households are also within 6 degrees of separation**.
All of which means that a virus can quickly get around from one household to the whole community!
[*Note: The technical term in network theory for a group of connected people is a "component", but we think the idea of a "cluster" is more familiar to most people*].
<br>
<br>
# Perfect isolation {.tabset .tabset-pills .tabset-fade}
Now let's imagine a world at the other extreme---complete and utter lock-down, where somehow we manage to keep every person in their household and never interact with anyone else. What does that look like?
## The Network
```{r emptynet, cache=TRUE, echo=FALSE, warning=FALSE, error=FALSE, message=FALSE, fig.height=4, fig.width=4, fig.align="center"}
par(mai=c(0,0,0,0))
plot(emptynet, vertex.cex=1.5,
mode="kamadakawai",
vertex.col=3,
edge.col="gray20")
```
**The virus would not be able to spread from household to household at all. Anyone who had it might pass it onto the other members of their household, and each of those people would either die or recover. But the virus could not spread to other households; it would quickly disappear.**
<br>
<br>
## What's going on?
Here, the **largest cluster is of size 1**: every household is isolated from every other household. And of course, **no household is within either 3 or 6 degrees of separation from any other.**
What does that mean? Here the virus would not be able to spread from household to household at all, because there are no links. Anyone who had it might pass it on to the other members of their household, and each of those people would either die or recover. But the virus could not spread to other households; it would quickly disappear.
<br>
<br>
# Adding in the essential workers {.tabset .tabset-pills .tabset-fade}
Of course, that world is impossible. Why? Because some people work in jobs that are essential to maintain the safety, health and well-being of all of us: health care workers, first responders, grocery store workers, etc.
So, let's imagine what this might do to our network.
Let's say that 1 in every 10 households contains someone with a job where they need to continue some connections. And the average number of connections they have is 4.
If we **color the households with an essential worker as blue**, that gives us...
## The Network
```{r essl.net, cache=TRUE, echo=FALSE, warning=FALSE, error=FALSE, message=FALSE, fig.height=4, fig.width=4, fig.align="center"}
meandeg.essl <- 4
prop.essl <- 0.1
essl <- rep(0, n)
essl[sample(1:n, round(prop.essl*n,0), replace=FALSE)] <- 1
set.vertex.attribute(emptynet, 'essl', essl)
fit.essl <- ergm(emptynet ~ edges + nodematch("essl", diff=TRUE, levels=1),
target.stats= c(meandeg.essl*prop.essl*n, 0),
control=control.ergm(MCMC.burnin = 1e6))
net.essl <- simulate(fit.essl,
control = control.simulate(MCMC.burnin = 1e6))
net.essl.el <- as.edgelist(net.essl)
par(mai=c(0,0,0,0))
plot(net.essl,
vertex.cex=1.5,
vertex.col=3+essl,
edge.col="gray20")
largcomp.essl <- sum(component.largest(net.essl))
geo.essl <- geo.sep(net.essl)
```
<br>
**The virus has some opportunity to move around here. This means that some people are going to get infected, and some people are going to die. It’s that simple. But these connections are so essential to the health and well-being of all of us that we as a society are willing to make that trade-off.**
<br>
<br>
## What's going on?
Even when States order people to "Stay Home", there are exceptions for essential workers:
- We need doctors and nurses and EMTs interacting with people.
- We need all the people that get food to us---growing it, transporting it, selling it---to interact with people.
- We need the people who manage and maintain our water supply and electricity and gas to keep showing up at work.
- We need first responders keeping us safe.
- In big cities, we need transport workers helping all of these people get back and forth between work and home.
- And so on.
It's hard to put real numbers on this, but we'll start with what seems like a reasonable example. Let's say they use hand washing and some distancing throughout the course of their work day as much as they can, so that they are able to bring their average effective contacts, in terms of reasonable transmission risk, down to 4.
You can see that the virus has some room to move around again---not nearly as much as in the days before social distancing, but still some. And it isn't just between the households with essential workers and their direct contacts. Sometimes the same household will be connected to two essential workers, creating a longer path. Sometimes two households with essential workers will end up directly connected, putting their two sets of contacts into the same path.
Altogether, we see here a **largest cluster of size `r largcomp.essl`, or `r round(100*largcomp.essl/n, 1)`%, of households.** (Can you find it?) This is a lot smaller than 100%, but still a fair bit bigger than 0%!
The average household has **`r round(geo.essl[1],1)` other households within 3 degrees of separation**, which represents `r round(100*geo.essl[1]/200, 2)`% of the community. There is some room for transmission to and from those you may know or know of, but not a lot.
Going out a bit futher, we see the average household has **`r round(geo.essl[2],1)` of households within 6 degrees of separation**, which represents `r round(100*geo.essl[2]/200, 2)`% of the community. So some additional room to spread the virus well beyond the set of people you know, and vice versa.
Let us be very clear here: some people are going to get infected, and some people are going to die, because of these connections. It's that simple.
But these connections are so essential that we as a society are willing to make that trade-off. Without them, many more people would die of other basic things besides COVID-19: starvation, freezing, crime, other diseases.
And hopefully, the deaths here won't be that high. First off, most households are still effectively isolated. And second, those that are connected are only held together by a pretty sparse set of ties, as reflected by the low number of 3-paths. Since transmission is not 100% guaranteed, not all of those in the same cluster as an infected person will become infected. This set of households are all **reachable** from one another, but it's not guaranteed that they will all actually be reached by a virus present in that cluster. The fewer the different routes connecting an infected person and a susceptible person, the less likely transmission will reach from one to the other.
<br>
<br>
# Visiting just one friend {.tabset .tabset-pills .tabset-fade}
But, we all know now: strict social distancing starts to get boring after a while. And meeting up to hang out with just one person outside your household---a friend especially---is pretty tempting. And it just doesn't seem like such a big deal when these other connections are already happening, right?
What happens if an average of two people in each household each decide to maintain an in-person social connection with one person from another household?
## The Network
```{r non.essl.net.1, cache=TRUE, echo=FALSE, warning=FALSE, error=FALSE, message=FALSE, fig.height=4, fig.width=4, fig.align="center"}
meandeg.non.essl.1 <- 2
fit.non.essl.1 <- ergm(emptynet ~ edges,
target.stats= meandeg.non.essl.1*n/2)
net.non.essl.1 <- simulate(fit.non.essl.1)
net.comb.1 <- net.non.essl.1
net.comb.1 <- add.edges(net.comb.1,
tail=net.essl.el[,1],
head=net.essl.el[,2])
par(mai=c(0,0,0,0))
plot(net.comb.1,
vertex.cex=1.5,
vertex.col=3+essl,
edge.col="gray20")
largcomp.comb.1 <- sum(component.largest(net.comb.1))
geo.comb.1 <- geo.sep(net.comb.1)
```
**This network is a lot more connected than the one with just essential workers.**
**Visiting your friend means that you can reach almost all the other households in your community, and they can reach you! That includes lots of people you don't even know. The virus can easily travel from them to you and then far beyond to many others. All before you even know you're infected. It’s a very connected, and effective, network of transmission.**
**All of that leads to lots of additional deaths, just so people can hang out with one friend.**
<br>
<br>
## What's going on?
Wow! This network is a lot more connected than the one with just essential workers.
Most households have more than one person in them. In fact, the **average household size in the US is 2.6 people.** Some households may have one, and others may have 10, but on average it's 2.6.
Let's say, then, that you decide to meet up with your friend Sue. But if Sue's parents are letting her go out, then they probably also need to let her brother Ed go out to meet up with his friend. Note that this is still less than the average household size---not everybody is meeting up with a friend.
What happens when we lay these new connections on top of the essential worker network? A lot more connectivity.
Indeed, the **largest cluster contains `r largcomp.comb.1`, or `r round(100*largcomp.comb.1/n, 1)`%, of households.** That is **`r round(largcomp.comb.1/largcomp.essl, 1)` times larger than the essential network.** If you are part of that large cluster, then now your household can reach `r round(100*largcomp.comb.1/n, 1)`% of the households in your community, and they can reach you!
And **households here have, on average, `r round(geo.comb.1[1],1)` other households within a mere 3 degrees of separation**. That's a *huge* increase from the `r round(geo.essl[1],1)` we saw for the essential worked-only network!
We same effect going out further to **6 degrees of separation**, where now households average **`r round(geo.comb.1[2],1)` connections**, vs. **`r round(geo.essl[2],1)`** for the essential worked-only network. That's another *enormous* increase!
In short, we see many many more opportunites to acquire the virus from folks who are both near and far from you in the social network. And equally more oppportunities for you to transmit it on to other folks both near and far.
All just so people can hang out with one friend!
<br>
<br>
# Visiting just one friend per household {.tabset .tabset-pills .tabset-fade}
OK, maybe households with multiple people could all agree that only one person can hang out with one friend. This seems like it should have a lot less connectivity, right?
## The Network
```{r non.essl.net.2, cache=TRUE, echo=FALSE, warning=FALSE, error=FALSE, message=FALSE, fig.height=4, fig.width=4, fig.align="center"}
meandeg.non.essl.2 <- 0.999
fit.non.essl.2 <- ergm(emptynet ~ edges + concurrent,
target.stats= c(meandeg.non.essl.2*n/2, 0))
net.non.essl.2 <- simulate(fit.non.essl.2,
control=control.simulate(MCMC.burnin=1e8))
net.comb.2 <- net.non.essl.2
net.comb.2 <- add.edges(net.comb.2,
tail=net.essl.el[,1],
head=net.essl.el[,2])
par(mai=c(0,0,0,0))
plot(net.comb.2,
vertex.cex=1.5,
vertex.col=3+essl,
edge.col="gray20")
largcomp.comb.2 <- sum(component.largest(net.comb.2))
geo.comb.2 <- geo.sep(net.comb.2)
```
**Even with just one person per household getting to see a friend, there's still a lot more connectivity than in the network with just essential worker ties. And thus, more transmission, and more infection.**
<br>
<br>
## What's going on?
Maybe parents don't feel like they need friend time as much as their kid does. Of course, if there are multiple kids, that creates a problem---eveyone will want to be the one who gets to hang out with their friend! But let's say we could make it work.
To examine this, then, we won't just set an *average* of one non-essential tie per household; we'll make every household have exactly one, and no more. Pairs of households become connected, but then they don't create the same chains that are possible when there are two connections per household. Bu this is still in addition to the essential worker connections. Does this create much less connectivity than the case of two friends per household? Not really.
This still creates a fair amount of connection---the **largest cluster contains `r largcomp.comb.2`.** That's still the majority of households, at **`r round(100*largcomp.comb.2/n, 1)`%,** and **`r round(largcomp.comb.2/largcomp.essl, 1)` times larger than the essential network.**
And households still have an average of **`r round(geo.comb.2[1],1)` households within 3 degrees of separation or `r round(geo.comb.2[2],1)` within 6 degrees**. *Still* much larger than the same numbers for the essential-worker network (`r round(geo.essl[1],1)` and `r round(geo.essl[2],1)`, respectively).
That still allows for a lot of extra transmissions and illnesses and hospitalizations and deaths.
<br>
<br>
# Lessons learned
```{r lessons}
# Compute geodesics
distances <- rbind( geo.sep(net.precov, 'Pre-Covid'),
geo.sep(emptynet, 'Pure Isolation'),
geo.sep(net.essl, 'Essential Only'),
geo.sep(net.comb.1, 'Just One Friend'),
geo.sep(net.comb.2, 'Just One Friend Per HH'))
# Labels
net.order <- c('Pre-Covid',
'Pure Isolation',
'Essential Only',
'Just One Friend',
'Just One Friend Per HH')
rownames(distances) <- net.order
```
**Humans are social animals, and reducing connectivity in social networks is hard.**
Some connections just can't broken at all if we want to maintain the basic functioning of the systems we need in place to all live. Other connections laid on top of those create more network connectivity than you might think. And thus:
**Every additional connection that we can postpone until COVID-19 is under control has the potential to save one or more lives.** Yes, **every one**.
You may never know whether it made a difference, and if it did, exactly whose life was saved.
- They may be multiple degrees of separation away from you.
- It could be your friend's mother's patient's father.
- It could be your sister's friend's grandfather's doctor.
- It could be the daughter of the grocery store worker where your friend's parents shop.
**Regardless of who it is---waiting a bit to hang out with your friends again is worth it!**
<br>
<br>
# Links to further exploration
As you read through this, did you find yourself wondering: how would all of this change---the network pictures, or the numbers on the "What's Going On?" tabs---if we made different assumptions? For instance, if we imagined that essential workers had fewer contacts? Or there were more essential workers? Or more households overall?
If so, then you're in luck---one of our readers, an environmental engineer from Bellingham, WA named Steve Hood---decided to code up an extended version of this page that explores different parameter values like these and more. You can find his site at: https://steve-hood.shinyapps.io/OneFriend/. Thank you, Steve H!
# The fine print for those who are interested {.tabset}
## Model caveats
Now, you may be thinking -- isn't this picture a bit simplistic, in a bunch of ways? Not everybody fits neatly into households; for example, some people live in group quarters like dorms or nursing homes, some kids divide their time between two parental households, and some people are homeless. Surely there is a lot more variation in connections among people than you seem to have here. It seems that, beyond a few simple rules about numbers of connections per household, you are assuming that households pick each other randomly, and surely there is a lot more structure to real networks than that. And surely relationships are actually dynamic---they form and break over time, and not everyone sees the same people from the same households every day.
All of those points are true. But we put them aside and purposefully simplified the world a bit so that we could gain some clear insight about those scenarios first. This is a common approach in scientific investigation in general, and network epidemiology in particular. Once one gains those insights, then one can begin adding in more complexity. Actual models used in the field of network epidemiology typically have a lot more complexity in them than the versions we look at here---but these are great for communicating basic principles to a broad audience.
<br>
<br>
## Model code
```{r full-code, eval=FALSE}
# Preliminaries: Install if you need these
#install.packages("flexdashboard")
#install.packages("statnet")
#install.packages("sna")
library(statnet)
library(sna)
## setup
n <- 200
emptynet <- network.initialize(n, directed=FALSE)
## pre-COVID network
meandeg.precov <- 15
fit.precov <- ergm(emptynet~edges,
target.stats=meandeg.precov*n/2)
net.precov <- simulate(fit.precov)
plot(net.precov,
vertex.cex=1.5,
mode="kamadakawai",
vertex.col=3,
edge.col="gray20")
largcomp.precov <- sum(component.largest(net.precov))
## empty network
plot(emptynet,
vertex.cex=1.5,
mode="kamadakawai",
vertex.col=3,
edge.col="gray20")
## essential network
meandeg.essl <- 4
prop.essl <- 0.1
essl <- rep(0, n)
essl[sample(1:n, round(prop.essl*n,0), replace=FALSE)] <- 1
set.vertex.attribute(emptynet, 'essl', essl)
fit.essl <- ergm(emptynet ~ edges + nodematch("essl", diff=TRUE, levels=1),
target.stats= c(meandeg.essl*prop.essl*n, 0),
control=control.ergm(MCMC.burnin = 1e6))
net.essl <- simulate(fit.essl,
control = control.simulate(MCMC.burnin = 1e6))
net.essl.el <- as.edgelist(net.essl)
plot(net.essl,
vertex.cex=1.5,
vertex.col=3+essl,
edge.col="gray20")
largcomp.essl <- sum(component.largest(net.essl))
kpath.essl <- sna:::kpath.census(net.essl)$path.count[3,'Agg']/2
## non.essl.net.1
meandeg.non.essl.1 <- 2
fit.non.essl.1 <- ergm(emptynet ~ edges,
target.stats= meandeg.non.essl.1*n/2)
net.non.essl.1 <- simulate(fit.non.essl.1)
net.comb.1 <- net.non.essl.1
net.comb.1 <- add.edges(net.comb.1, tail=net.essl.el[,1], head=net.essl.el[,2])
plot(net.comb.1,
vertex.cex=1.5,
vertex.col=3+essl,
edge.col="gray20")
largcomp.comb.1 <- sum(component.largest(net.comb.1))
kpath.comb.1 <- sna:::kpath.census(net.comb.1)$path.count[3,'Agg']/2
## non.essl.net.2
meandeg.non.essl.2 <- 1
fit.non.essl.2 <- ergm(emptynet ~ edges + concurrent,
target.stats= c(meandeg.non.essl.2*n/2, 0))
net.non.essl.2 <- simulate(fit.non.essl.2,
control=control.simulate(MCMC.burnin=1e8))
net.comb.2 <- net.non.essl.2
net.comb.2 <- add.edges(net.comb.2, tail=net.essl.el[,1], head=net.essl.el[,2])
plot(net.comb.2,
vertex.cex=1.5,
vertex.col=3+essl,
edge.col="gray20")
largcomp.comb.2 <- sum(component.largest(net.comb.2))
kpath.comb.2 <- sna:::kpath.census(net.comb.2)$path.count[3,'Agg']/2
```
For those of you who find this interesting and have some coding skills in R, this document contains the code you need to reproduce all of the examples on this website -- just click the "SHOW" button in the right margin above to see/copy the code for all sections. Feel free to play with the code, try changing values or add complexity as you wish. If you come up with something interesting, [let us know](mailto:[email protected])!
Note that these examples were created using the [*statnet*](https://statnet.org) suite of R packages for statistical network analysis, simulation and vizualization. Thank you goes to the full **statnet development team** for their work. Full citation information for the version of *statnet* used to produce this website is:
Mark S. Handcock, David R. Hunter, Carter T. Butts, Steven M. Goodreau, Pavel N. Krivitsky, Skye Bender-deMoll, and Martina Morris (2024). statnet: Software tools for the Statistical Modeling of Network Data. version 2019.6. URL https://statnet.org, https://cran.r-project.org/web/packages/statnet/.
The examples here represent a tiny fraction of what can be done with *statnet*. If you're interested in research-level epidemic modeling on networks, check out the [*EpiModel*](https://epimodel.org) package, which uses *statnet* to provide a robust platform for stochastic dynamic network modeling for epidemics.
# Citation info
Goodreau SM, Pollock ED, Birnbaum JK, Hamilton DT, Morris M, on behalf of the Statnet Development Team. 2020. *Can't I please just visit one friend?: Visualizing social distancing networks in the era of COVID-19*. http://statnet.org/COVID-JustOneFriend/