Lists in R are collections of objects that can be of any mix of types (or all the same type). They can be useful when dealing with multiple data.frames that each correspond to a different unit of study (note that we solved this before by considering a single data.frame with a column corresponding to country). Lists tend to be useful in my research when I’m simulating ecological dynamics, where each list item can be the results of a single simulation, or when I’m writing functions to return data that is not really structured as a data.frame. Before we go too far into use cases, lets refresh on how we form and index list objects.
lst <- list(a=runif(100), df=data.frame(x=runif(100), y=runif(100)), letters[1:10], 'a')
# index single list elements
lst[[1]]
## [1] 0.34046289 0.94643405 0.05357835 0.68162070 0.96725082 0.46552435
## [7] 0.46193021 0.24773629 0.84685165 0.04951064 0.07709970 0.74341435
## [13] 0.62718010 0.28817302 0.01982099 0.65789793 0.28729076 0.97397297
## [19] 0.44789942 0.46784946 0.78985399 0.91293382 0.91485528 0.12936998
## [25] 0.52169951 0.30319469 0.99060980 0.72079305 0.37018121 0.79486462
## [31] 0.58259950 0.97563316 0.25120744 0.81068821 0.73903576 0.31250856
## [37] 0.21539792 0.20502087 0.14643692 0.86203493 0.15094042 0.02199761
## [43] 0.18272179 0.65591518 0.22985631 0.01809413 0.32869825 0.26868559
## [49] 0.76882045 0.70379998 0.90121216 0.38417143 0.04636957 0.24065698
## [55] 0.68231068 0.67263555 0.73413866 0.02280526 0.71578088 0.25659874
## [61] 0.31017177 0.27531887 0.62087924 0.11068232 0.13597382 0.63055170
## [67] 0.08644377 0.53472327 0.96119677 0.48211682 0.63788943 0.82100326
## [73] 0.75117073 0.15140766 0.40291645 0.74576717 0.61099719 0.11678347
## [79] 0.37377297 0.09278750 0.64977205 0.56694935 0.99595551 0.73036531
## [85] 0.14137578 0.62296244 0.25702466 0.62392033 0.65314891 0.99843399
## [91] 0.03201989 0.83054294 0.66959682 0.51498838 0.62117112 0.64042694
## [97] 0.77149807 0.87215743 0.39819031 0.31460425
## x y
## 1 0.599313413 0.7451304304
## 2 0.040862446 0.5167818672
## 3 0.210753933 0.1523553713
## 4 0.708424325 0.2271739002
## 5 0.175310978 0.4061014836
## 6 0.633776495 0.3877668097
## 7 0.755728533 0.1145512382
## 8 0.501242496 0.5361059972
## 9 0.852528092 0.9617803788
## 10 0.629468479 0.4463521603
## 11 0.306226669 0.7620533258
## 12 0.806083132 0.0159623229
## 13 0.224154367 0.7021007321
## 14 0.614856688 0.2908176871
## 15 0.433900651 0.8918489434
## 16 0.093666297 0.0266604936
## 17 0.225939720 0.3662482027
## 18 0.226365995 0.6490608470
## 19 0.949763810 0.1270814410
## 20 0.610454535 0.4187681451
## 21 0.891566462 0.7450404242
## 22 0.646783066 0.4923762935
## 23 0.723263559 0.0034591982
## 24 0.787699236 0.7074046710
## 25 0.516187326 0.5193615276
## 26 0.839063108 0.1549629471
## 27 0.163775654 0.2068551152
## 28 0.220425262 0.6412772723
## 29 0.032557043 0.9725517528
## 30 0.998888442 0.9579255008
## 31 0.031282426 0.3534095772
## 32 0.496294864 0.1040291172
## 33 0.236717735 0.5218307562
## 34 0.827213963 0.0518988643
## 35 0.545478079 0.6326006069
## 36 0.029418744 0.4391015458
## 37 0.849487006 0.7406421157
## 38 0.166160220 0.8543559723
## 39 0.447026670 0.6579116643
## 40 0.286158861 0.4818595201
## 41 0.770246402 0.3304628392
## 42 0.683525098 0.1422758687
## 43 0.402910245 0.8106133398
## 44 0.443489176 0.0006682384
## 45 0.688485764 0.2971684043
## 46 0.232268608 0.5164680798
## 47 0.986282516 0.3632544917
## 48 0.689779273 0.3991962532
## 49 0.526765611 0.5805767882
## 50 0.375395916 0.1811128717
## 51 0.500863336 0.2404785019
## 52 0.351937549 0.1427278151
## 53 0.246507443 0.6361539487
## 54 0.444648757 0.4252010041
## 55 0.902123126 0.1267686265
## 56 0.425277065 0.9873593606
## 57 0.460280739 0.5554125845
## 58 0.889349713 0.4442451177
## 59 0.751835463 0.4532812154
## 60 0.622930990 0.2642223197
## 61 0.759629962 0.6025177692
## 62 0.920253018 0.9584879105
## 63 0.899584176 0.4812389452
## 64 0.021319917 0.8603284117
## 65 0.514585556 0.8360792988
## 66 0.578941352 0.5178508472
## 67 0.847277774 0.7523158689
## 68 0.339111006 0.1643893782
## 69 0.827040503 0.9475075565
## 70 0.162093920 0.4754983080
## 71 0.819212348 0.7917486297
## 72 0.005039564 0.7467947206
## 73 0.454431651 0.1519718575
## 74 0.649278169 0.9371584775
## 75 0.594943066 0.1865730861
## 76 0.673319862 0.5360196489
## 77 0.604815902 0.5213458382
## 78 0.970395627 0.4607918286
## 79 0.604433516 0.6627412613
## 80 0.428314971 0.5078915481
## 81 0.964913370 0.5648929076
## 82 0.750348529 0.1354797676
## 83 0.066287536 0.9048296462
## 84 0.342218303 0.0448320368
## 85 0.572434363 0.8260065743
## 86 0.874340653 0.0047246537
## 87 0.718316944 0.4066896420
## 88 0.331875166 0.4063805994
## 89 0.366953323 0.7967686448
## 90 0.819545025 0.2163760737
## 91 0.532927902 0.6403135061
## 92 0.241291568 0.8334639890
## 93 0.497296680 0.2958797016
## 94 0.313805835 0.9093010423
## 95 0.034858146 0.6265365011
## 96 0.004078905 0.3857606971
## 97 0.191835816 0.0535620051
## 98 0.623974349 0.7442414870
## 99 0.133656989 0.4862722317
## 100 0.860498165 0.7433155261
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
## [1] "a"
## $a
## [1] 0.34046289 0.94643405 0.05357835 0.68162070 0.96725082 0.46552435
## [7] 0.46193021 0.24773629 0.84685165 0.04951064 0.07709970 0.74341435
## [13] 0.62718010 0.28817302 0.01982099 0.65789793 0.28729076 0.97397297
## [19] 0.44789942 0.46784946 0.78985399 0.91293382 0.91485528 0.12936998
## [25] 0.52169951 0.30319469 0.99060980 0.72079305 0.37018121 0.79486462
## [31] 0.58259950 0.97563316 0.25120744 0.81068821 0.73903576 0.31250856
## [37] 0.21539792 0.20502087 0.14643692 0.86203493 0.15094042 0.02199761
## [43] 0.18272179 0.65591518 0.22985631 0.01809413 0.32869825 0.26868559
## [49] 0.76882045 0.70379998 0.90121216 0.38417143 0.04636957 0.24065698
## [55] 0.68231068 0.67263555 0.73413866 0.02280526 0.71578088 0.25659874
## [61] 0.31017177 0.27531887 0.62087924 0.11068232 0.13597382 0.63055170
## [67] 0.08644377 0.53472327 0.96119677 0.48211682 0.63788943 0.82100326
## [73] 0.75117073 0.15140766 0.40291645 0.74576717 0.61099719 0.11678347
## [79] 0.37377297 0.09278750 0.64977205 0.56694935 0.99595551 0.73036531
## [85] 0.14137578 0.62296244 0.25702466 0.62392033 0.65314891 0.99843399
## [91] 0.03201989 0.83054294 0.66959682 0.51498838 0.62117112 0.64042694
## [97] 0.77149807 0.87215743 0.39819031 0.31460425
##
## $df
## x y
## 1 0.599313413 0.7451304304
## 2 0.040862446 0.5167818672
## 3 0.210753933 0.1523553713
## 4 0.708424325 0.2271739002
## 5 0.175310978 0.4061014836
## 6 0.633776495 0.3877668097
## 7 0.755728533 0.1145512382
## 8 0.501242496 0.5361059972
## 9 0.852528092 0.9617803788
## 10 0.629468479 0.4463521603
## 11 0.306226669 0.7620533258
## 12 0.806083132 0.0159623229
## 13 0.224154367 0.7021007321
## 14 0.614856688 0.2908176871
## 15 0.433900651 0.8918489434
## 16 0.093666297 0.0266604936
## 17 0.225939720 0.3662482027
## 18 0.226365995 0.6490608470
## 19 0.949763810 0.1270814410
## 20 0.610454535 0.4187681451
## 21 0.891566462 0.7450404242
## 22 0.646783066 0.4923762935
## 23 0.723263559 0.0034591982
## 24 0.787699236 0.7074046710
## 25 0.516187326 0.5193615276
## 26 0.839063108 0.1549629471
## 27 0.163775654 0.2068551152
## 28 0.220425262 0.6412772723
## 29 0.032557043 0.9725517528
## 30 0.998888442 0.9579255008
## 31 0.031282426 0.3534095772
## 32 0.496294864 0.1040291172
## 33 0.236717735 0.5218307562
## 34 0.827213963 0.0518988643
## 35 0.545478079 0.6326006069
## 36 0.029418744 0.4391015458
## 37 0.849487006 0.7406421157
## 38 0.166160220 0.8543559723
## 39 0.447026670 0.6579116643
## 40 0.286158861 0.4818595201
## 41 0.770246402 0.3304628392
## 42 0.683525098 0.1422758687
## 43 0.402910245 0.8106133398
## 44 0.443489176 0.0006682384
## 45 0.688485764 0.2971684043
## 46 0.232268608 0.5164680798
## 47 0.986282516 0.3632544917
## 48 0.689779273 0.3991962532
## 49 0.526765611 0.5805767882
## 50 0.375395916 0.1811128717
## 51 0.500863336 0.2404785019
## 52 0.351937549 0.1427278151
## 53 0.246507443 0.6361539487
## 54 0.444648757 0.4252010041
## 55 0.902123126 0.1267686265
## 56 0.425277065 0.9873593606
## 57 0.460280739 0.5554125845
## 58 0.889349713 0.4442451177
## 59 0.751835463 0.4532812154
## 60 0.622930990 0.2642223197
## 61 0.759629962 0.6025177692
## 62 0.920253018 0.9584879105
## 63 0.899584176 0.4812389452
## 64 0.021319917 0.8603284117
## 65 0.514585556 0.8360792988
## 66 0.578941352 0.5178508472
## 67 0.847277774 0.7523158689
## 68 0.339111006 0.1643893782
## 69 0.827040503 0.9475075565
## 70 0.162093920 0.4754983080
## 71 0.819212348 0.7917486297
## 72 0.005039564 0.7467947206
## 73 0.454431651 0.1519718575
## 74 0.649278169 0.9371584775
## 75 0.594943066 0.1865730861
## 76 0.673319862 0.5360196489
## 77 0.604815902 0.5213458382
## 78 0.970395627 0.4607918286
## 79 0.604433516 0.6627412613
## 80 0.428314971 0.5078915481
## 81 0.964913370 0.5648929076
## 82 0.750348529 0.1354797676
## 83 0.066287536 0.9048296462
## 84 0.342218303 0.0448320368
## 85 0.572434363 0.8260065743
## 86 0.874340653 0.0047246537
## 87 0.718316944 0.4066896420
## 88 0.331875166 0.4063805994
## 89 0.366953323 0.7967686448
## 90 0.819545025 0.2163760737
## 91 0.532927902 0.6403135061
## 92 0.241291568 0.8334639890
## 93 0.497296680 0.2958797016
## 94 0.313805835 0.9093010423
## 95 0.034858146 0.6265365011
## 96 0.004078905 0.3857606971
## 97 0.191835816 0.0535620051
## 98 0.623974349 0.7442414870
## 99 0.133656989 0.4862722317
## 100 0.860498165 0.7433155261
Let’s think about how we might use lists. For one, many functions in
R output data in list format. For instance, working with network data in
R through igraph
, most things are lists. Let’s explore
this, both as a way to introduce lists and to talk about how to analyze
network data in R.
##
## Attaching package: 'igraph'
## The following object is masked from 'package:tidyr':
##
## crossing
## The following objects are masked from 'package:dplyr':
##
## as_data_frame, groups, union
## The following objects are masked from 'package:terra':
##
## blocks, compare, union
## The following objects are masked from 'package:stats':
##
## decompose, spectrum
## The following object is masked from 'package:base':
##
## union
## Class 'igraph' hidden list of 10
## $ : num 100
## $ : logi FALSE
## $ : num [1:200] 1 12 15 18 19 22 22 23 23 24 ...
## $ : num [1:200] 0 5 5 7 12 5 13 5 9 7 ...
## $ : NULL
## $ : NULL
## $ : NULL
## $ : NULL
## $ :List of 4
## ..$ : num [1:3] 1 0 1
## ..$ :List of 4
## .. ..$ name : chr "Erdos-Renyi (gnm) graph"
## .. ..$ type : chr "gnm"
## .. ..$ loops: logi FALSE
## .. ..$ m : num 200
## ..$ : Named list()
## ..$ : Named list()
## $ :<environment: 0x622d32098ad8>
Recall when we introduced the plot
function, and I said
that packages build in functionality such that some base functions will
work with more complex objects (the igraph
object above is
a list). Try it here.
Nice. That’s neat. We can also write a wrapper function (we will not go over function writing now, but will save that for the coming weeks), which can be useful across multiple projects. This is a function I routinely use for visualizing networks in a prettier way.
#' @param g graph object
#' @param colz
#' @param nodeColor
#' @param nodeSize
#'
#' @return a graph plot
plotGraph <- function(g, lay=layout_nicely(g), colz='dodgerblue'){
plot(g, layout=lay, edge.width= E(g)$weight, vertex.size=10, directed=FALSE,
vertex.color= colz,
vertex.label=NA)
}
plotGraph(g)
But let’s get back to lists. We’ve seen that igraph
graph objects are lists, but also many of the outputs of functions
within igraph
are lists (or even lists of lists!). I will
not defend nested lists as being all that useful, but we will see them
in a couple of weeks when we talk about APIs and spatial data.
So one of the functions built into igraph
is the
sir
function. This is a function which runs a model on the
network known as the Susceptible-Infected-Recovered model (or SIR for
short), which aims to capture how diseases spread through
populations.
\[\begin{align} \frac{dS}{dt} & = -\beta SI \\ \frac{dI}{dt} & = \beta SI - \gamma I \\ \frac{dR}{dt} & = \gamma I \end{align}\]
The default behavior of the function (?sir
) will run 100
simulations of the SIR model on a graph object that you provide to the
function, and store the output as a list.
## [1] "list"
## [1] "sir"
## $times
## [1] 0.00000000 0.04811261
##
## $NS
## [1] 99 99
##
## $NI
## [1] 1 0
##
## $NR
## [1] 0 1
## [1] 0.00000000 0.04811261
## [1] 0.00000000 0.04811261
And just to go back to plotting for a quick second,
igraph
has written functionality into the sir
class to work well with the base R plot
function.
Neat, right?
But back to lists. Let’s work through the rest of working with lists
through some exercises. Given the simulations above (sims
list) …
Calculate the mean number of infected individuals for each simulation
Find the time associated with the maximum number of infected nodes
Calculate the fraction of all simulations in which fewer than 5 nodes are infected
How did we approach the above questions? You almost certaintly used a
for
loop, right? This is perfectly fine, but there is
another way. apply
statements allow you to take a function
and run it over all elements of a vector, columns/rows of a matrix, or a
list.
apply
statements typically have a prefix which gives
information about what type of data it works well with. For instance,
working with lists, we will use lapply
. The base
apply
function is to work with matrices, where we want to
apply a function to every row or column of a matrix (e.g.,
apply(matrix, 2, sum)
is the same as
colSums(matrix)
). We will go over more examples of
apply
statements at some point, but for now we will focus
on lapply
and our problem of working with lists.
And here we hit an issue. lapply
statements take a
function argument, where the function needs to take the list object as
an argument and then does something with it. So we’ll have to learn a
bare minimum of function writing now. Let’s use a problem above as a
motivating example, where we try to calculate the mean number of
infected individuals for each simulation.
meanInfections <- function(x){
# if we consider the mean infecteds as the mean of the infected vector
return(mean(x$NI))
# if we consider the mean infecteds as the mean number of nodes infected
# return((x$NS[1]+1)-tail(x$NS,1))
}
meanInfs <- lapply(sims, meanInfections)
str(meanInfs)
## List of 100
## $ : num 0.5
## $ : num 24
## $ : num 25
## $ : num 0.5
## $ : num 20
## $ : num 21.9
## $ : num 24
## $ : num 0.5
## $ : num 0.5
## $ : num 1.5
## $ : num 18.4
## $ : num 0.5
## $ : num 23.8
## $ : num 21
## $ : num 1
## $ : num 1.17
## $ : num 13.6
## $ : num 0.5
## $ : num 22.5
## $ : num 15.6
## $ : num 24.8
## $ : num 0.5
## $ : num 24
## $ : num 14.7
## $ : num 0.5
## $ : num 20.4
## $ : num 0.5
## $ : num 19.5
## $ : num 1.17
## $ : num 24.3
## $ : num 20.1
## $ : num 27.3
## $ : num 1.5
## $ : num 24.8
## $ : num 25.7
## $ : num 0.5
## $ : num 18.8
## $ : num 12.9
## $ : num 20.9
## $ : num 20.5
## $ : num 21.5
## $ : num 0.5
## $ : num 22.8
## $ : num 0.5
## $ : num 0.5
## $ : num 15.6
## $ : num 24.7
## $ : num 0.5
## $ : num 0.5
## $ : num 1
## $ : num 15.4
## $ : num 27.4
## $ : num 0.5
## $ : num 0.5
## $ : num 11.9
## $ : num 0.5
## $ : num 14.9
## $ : num 0.5
## $ : num 0.5
## $ : num 29.9
## $ : num 0.5
## $ : num 13.9
## $ : num 1.17
## $ : num 26.3
## $ : num 23.6
## $ : num 19.1
## $ : num 22.6
## $ : num 1.5
## $ : num 1.5
## $ : num 14.4
## $ : num 0.5
## $ : num 1
## $ : num 20.5
## $ : num 0.5
## $ : num 0.5
## $ : num 0.5
## $ : num 22.6
## $ : num 17.1
## $ : num 1
## $ : num 0.5
## $ : num 21
## $ : num 0.5
## $ : num 0.5
## $ : num 0.5
## $ : num 19
## $ : num 27
## $ : num 2.1
## $ : num 3.21
## $ : num 23.5
## $ : num 0.5
## $ : num 17.5
## $ : num 4.74
## $ : num 1
## $ : num 12.2
## $ : num 9.56
## $ : num 25.9
## $ : num 0.5
## $ : num 20.1
## $ : num 1.5
## [list output truncated]
lapply
is nice in that if we give it a list object, it
gives us a list object back. This makes analytical pipelines that deal
with lists pretty straightforward, but if the output is a single value,
we may want this to be a vector instead of a list.
## [1] 0.500000 24.018519 25.043478 0.500000 19.951220 21.897590 24.027473
## [8] 0.500000 0.500000 1.500000 18.428571 0.500000 23.848315 21.000000
## [15] 1.000000 1.166667 13.597222 0.500000 22.488889 15.628571 24.805882
## [22] 0.500000 23.973118 14.718750 0.500000 20.433333 0.500000 19.547619
## [29] 1.166667 24.276471 20.082278 27.288235 1.500000 24.768293 25.652941
## [36] 0.500000 18.804348 12.905405 20.872093 20.512987 21.546512 0.500000
## [43] 22.829670 0.500000 0.500000 15.563291 24.715909 0.500000 0.500000
## [50] 1.000000 15.434211 27.400000 0.500000 0.500000 11.905797 0.500000
## [57] 14.949275 0.500000 0.500000 29.938202 0.500000 13.852113 1.166667
## [64] 26.290698 23.558824 19.141026 22.584337 1.500000 1.500000 14.355556
## [71] 0.500000 1.000000 20.512048 0.500000 0.500000 0.500000 22.576923
## [78] 17.063380 1.000000 0.500000 20.993976 0.500000 0.500000 0.500000
## [85] 19.025641 26.988095 2.100000 3.214286 23.537975 0.500000 17.524096
## [92] 4.735294 1.000000 12.237500 9.562500 25.948276 0.500000 20.097403
## [99] 1.500000 1.000000
sapply
statements are essentially just
lapply
statements that simplify the result to a vector.
This is useful when the output of the function is a single value, and
not so useful when function returns multiple values.
A side note: some people will criticize for
loops in R, and say “just use apply, it’s faster”. It’s not, really.
Write however you feel comfortable. For awhile, apply
statements were super confusing to me, so I tended to use
for
loops instead. After more work in, I shifted and tend
to use apply
statements when it fits, as they are less code
and are more intuitive to me for many situations.
Calculate the maximum number of infected inviduals at any time in the
sims
list using the apply
approach.
What is the mean duration (the total time the epidemic took before it
stopped) across all the epidemics in sims
?
XYply
statements as nice wrappers to more classic
apply
statements. Here, X
and Y
can take values of ‘a’, ‘l’, or ‘d’, depending on the input or output
data structure desired. For instance, if we have a list that we would
like to apply over and return a data.frame, we would use
ldply
, where the l
is claiming that the input
is a list object, and the d
is claiming that the output
should be formatted as a data.frame. Other examples of this syntax would
be adply
, ddply
, laply
,
aaply
, etc. etc.
Below, I provide an example of the aXply syntax (e.g., adply, alply, aaply).
arr <- array(1:27, c(3,3,3))
rownames(arr) = c("Curly", "Larry", "Moe")
colnames(arr) = c("Groucho", "Harpo", "Zeppo")
dimnames(arr)[[3]] = c("Bart", "Lisa", "Maggie")
arr
## , , Bart
##
## Groucho Harpo Zeppo
## Curly 1 4 7
## Larry 2 5 8
## Moe 3 6 9
##
## , , Lisa
##
## Groucho Harpo Zeppo
## Curly 10 13 16
## Larry 11 14 17
## Moe 12 15 18
##
## , , Maggie
##
## Groucho Harpo Zeppo
## Curly 19 22 25
## Larry 20 23 26
## Moe 21 24 27
Arrays are something that we did not introduce when we talked about
R
basics, and that is because they really are not used
too often. Think of matrix. It has two dimensions (x and y), so
it can be viewed as a rectangle of data. Arrays simply add more
dimensions. In the example above, there is another dimension, forming a
data cube (in the rectangle analogy).
We can use plyr
functionality to operate on this array
and return different forms. For instance, aaply
takes an
array and returns a simplified array (here a vector).
## Curly Larry Moe
## 117 126 135
We can change one letter and now return a data.frame containing two
columns. This is also a good time to point out the flexibility of the
XYply statements to different margins. Margins (denoted as
.margins
argument in R
, asks along which axis
you would like to operate on the array). If we set .margins=1, this
corresponds to a row-wise operation, so we calculate the sum across the
array for Curly, Larry, and Moe. If we change this to .margins=2, we
operate on columns, and will return sums for Groucho, Harpo, and Zeppo.
And if we use .margins=3, we will return sums for Bart, Lisa, and
Maggie.
## X1 V1
## 1 Curly 117
## 2 Larry 126
## 3 Moe 135
## X1 V1
## 1 Groucho 99
## 2 Harpo 126
## 3 Zeppo 153
## X1 V1
## 1 Bart 45
## 2 Lisa 126
## 3 Maggie 207
Finally, we can return a list object. In this use case, this is not super helpful, but in other use cases the list output is pretty helpful.
## $`1`
## [1] 117
##
## $`2`
## [1] 126
##
## $`3`
## [1] 135
##
## attr(,"split_type")
## [1] "array"
## attr(,"split_labels")
## X1
## 1 Curly
## 2 Larry
## 3 Moe
A pitch for plyr::ldply
. I really like this function, as
I often find myself with lists of similar structures that I want to
operate on and get a single clean object back. I will not go into an
example, but this is a pretty useful function (though all the utility is
basically contained in vapply
).
Finally, you may wonder why am I pushing apply statements so hard. It
has nothing to do with speed, and only a bit to do with code clarity.
The main advantage is understanding the programmatic nature of apply
statements (which will be similar but less chronological than a for
loop), and many parallel computing packages have their own little
versions of apply statements ready to go (e.g.,
parallel::mclapply
, parallel::parLapply
,
parallel::clusterApplyLB
).
Let’s do one practice problem to showcase the utility of
ldply
specifically.
Calculate the correlation between number of infections and time for
each simulation, reporting the estimate, p-value, and confidence
intervals around the estimate. (you will use cor.test
to do
this, whose output is a list object as well)
While a bit opaque, these functions are pretty useful in a variety of
situations. Speaking of data manipulation functions that are useful but
a bit conceptually difficult, do.call
and
Reduce
are solid base R
functions.
do.call
is a way of calling the same function
recursively on multiple objects, and may have similar output to
Reduce
, which is also a way to recursively apply a
function.
## [[1]]
## [1] 1 2 3 4 5 6 7 8 9 10
##
## [[2]]
## [1] 1 2 3 4 5 6 7 8 9 10
##
## [[3]]
## [1] 1 2 3 4 5 6 7 8 9 10
##
## [[4]]
## [1] 1 2 3 4 5 6 7 8 9 10
##
## [[5]]
## [1] 1 2 3 4 5 6 7 8 9 10
#this makes a single rbind call with each element of the list as an argument
str(do.call(rbind, lst))
## int [1:5, 1:10] 1 1 1 1 1 2 2 2 2 2 ...
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## init 1 2 3 4 5 6 7 8 9 10
## 1 2 3 4 5 6 7 8 9 10
## 1 2 3 4 5 6 7 8 9 10
## 1 2 3 4 5 6 7 8 9 10
## 1 2 3 4 5 6 7 8 9 10
## R version 4.5.0 (2025-04-11)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 22.04.5 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3.10.3
## LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3; LAPACK version 3.10.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: America/New_York
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] igraph_2.1.4 tidyr_1.3.1 dplyr_1.1.4 plyr_1.8.9 DBI_1.2.3
## [6] geodata_0.5-8 terra_1.8-50 sf_1.0-21 rgbif_3.7.7 jsonlite_1.8.9
## [11] httr_1.4.7
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.6 xfun_0.49 bslib_0.8.0 ggplot2_3.5.1
## [5] vctrs_0.6.5 tools_4.5.0 generics_0.1.4 curl_6.0.1
## [9] tibble_3.2.1 proxy_0.4-27 RSQLite_2.3.7 blob_1.2.4
## [13] pkgconfig_2.0.3 KernSmooth_2.23-26 data.table_1.16.2 dbplyr_2.5.0
## [17] lifecycle_1.0.4 compiler_4.5.0 stringr_1.5.1 munsell_0.5.1
## [21] codetools_0.2-19 htmltools_0.5.8.1 maps_3.4.1 class_7.3-23
## [25] sass_0.4.9 yaml_2.3.10 lazyeval_0.2.2 pillar_1.10.2
## [29] jquerylib_0.1.4 whisker_0.4.1 classInt_0.4-11 cachem_1.1.0
## [33] tidyselect_1.2.1 digest_0.6.37 stringi_1.8.4 purrr_1.0.2
## [37] fastmap_1.2.0 grid_4.5.0 colorspace_2.1-1 cli_3.6.5
## [41] magrittr_2.0.3 utf8_1.2.5 triebeard_0.4.1 crul_1.5.0
## [45] e1071_1.7-16 withr_3.0.2 scales_1.3.0 bit64_4.5.2
## [49] oai_0.4.0 rmarkdown_2.29 bit_4.5.0 memoise_2.0.1
## [53] evaluate_1.0.1 knitr_1.49 rlang_1.1.6 urltools_1.7.3
## [57] Rcpp_1.0.14 glue_1.8.0 httpcode_0.3.0 xml2_1.3.6
## [61] R6_2.6.1 units_0.8-7