[1] 1
[1] 2
[1] 3
Loops in R
Looping is the repeated evaluation of a statement or block of statements.
What is a loop (in R
)?
Looping is the repeated evaluation of a statement or block of statements. Base R
provides functions for explicit (i.e., for
, while
, repeat
) and implicit looping (e.g., apply
, sapply
, lapply
,…). There are also other packages (e.g., parallel
, purrr
, furrr
) that offer more advanced or parallelized looping capabilities, providing more efficient and convenient ways to iterate over data, particularly for complex workflows or large datasets.
lapply
We begin by using the lapply
function that applies a function over a list or vector. The function needs 2 arguments as inputs:
X
: a vector (atomic or list)FUN
: the function to be applied to each element ofX
lapply
returns a list of the same length as the input X
(see ?lapply
).
Two (nearly equivalent) examples with lapply
:
- 1
-
Defines an so-called anonymous function that takes an argument
x
. - 2
-
This approach offers further customization of operations such as calculating the square of
x
(for more see Functions in R).
[1] 1
[1] 4
[1] 9
If the function()
becomes more complex, it might be better to define it separately (and save in your src
folder, see the section on Structure and Create the Project Folder(s)).
Example: Calculating many scale scores
In this example, we calculate many scale scores by using a named list and the sapply
function. sapply
is a user-friendly version and wrapper of lapply by default returning a vector, matrix or, if simplify = "array"
, an array […].
- The
calcScaleScore
function that is explained in the section What is a function inR
?.
Code
calcScaleScore <- function( data,
items,
score = "sum" ) {
validItems <- items %in% colnames(data)
missingItems <- items[!validItems]
if (length(missingItems) > 0) {
stop("The following item(s) is/are not in the dataset: ",
paste(missingItems, collapse = ", "))
}
if (score == "sum") {
ret <- rowSums(data[,items])
} else if ( score == "mean" ) {
ret <- rowMeans(data[,items])
} else {
stop("score argument must be either 'sum' or 'mean'")
}
return(ret)
}
- A simulated data set (
wideLSdat
) that can be found in the Example Data section.
- a named list (
wideLSVar
).
wideLSdat[,names(wideLSVar)] <- sapply(
X = wideLSVar,
FUN = function(x) {
ret <- calcScaleScore(data = wideLSdat,
items = x)
return(ret)
},simplify = F)
head(wideLSdat[,names(wideLSVar)])
Y1 Y2 Y3
1 -2.680416 2.2974542 3.8943707
2 2.944144 3.4948176 3.1198335
3 -1.403956 1.5638600 2.1539978
4 -2.010152 -2.9952976 -3.7823288
5 -4.117428 -3.3980176 0.6669694
6 -2.701068 0.9692462 3.7553657
When not to loop?
Answer: If vectorization is possible…
Example: Create a large vector (10 million random values) and multiply it by 2.
set.seed(999)
<- rnorm(1e7) x
Loop approach
But, How to know that vectorization is possible?
→ Especially, in coding situations where you need to perform the same operation on each element1 (e.g., vector, matrix):
- Arithmetic operations (e.g,
+
,-
, …) - Logical comparisons (e.g.,
==
,>
, …) - Mathematical functions (e.g.,
sqrt()
,log()
, …)
Create Sections in Quarto Programmatically
In this section, we will generate headings by iterating through a named list. The elements of the list will be hyperlinks to Wikipedia, but they can also be other types of content, such as tables or figures.
Named list
for loop
To generate the sections (recall, headings are created by using #
, ##
, etc.) for all elements, we use a for
loop. All content is wrapped in the cat()
function that concatenates and prints the input to plain text. To tell Quarto to treat the content as raw markdown, we set the output
option to asis
. For a more detailed description of the code, see the code-annotations
below the code.
Be generous with "\n"
as it creates a new line.
Code
```{r}
#| label: create-section
#| code-fold: show
1#| output: asis
#| code-annotations: select
2for (i in seq_along(someInfo) ) {
if (i == 1) {
cat("\n### Programmatically generated headings\n")
}
3 cat("\n#### ", names(someInfo)[i], "\n")
cat("In this section, we provide some information about",
paste0(tolower(names(someInfo)[i]), ".\n"))
4 cat("\n::: {.column-margin}\n", "Link to wikipedia: ",
someInfo[[i]],
"\n:::\n")
5 cat("\n{{< lipsum 1 >}}\n")
}
```
- 1
-
Set
output
chunk option toasis
. - 2
-
Open
for
loop, which iterates through thesomeInfo
list. - 3
-
State
####
before thenames(someInfo)
object within thecat()
function to create sections. - 4
-
(Optional): Positioning content in the margin of the document: Use a div with the
.column-margin
class. - 5
-
(Optional): Adding placeholder text:
{{< lipsum >}}
Programmatically generated headings
Apples
In this section, we provide some information about apples.
Link to wikipedia: https://en.wikipedia.org/wiki/Apple
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sagittis posuere ligula sit amet lacinia. Duis dignissim pellentesque magna, rhoncus congue sapien finibus mollis. Ut eu sem laoreet, vehicula ipsum in, convallis erat. Vestibulum magna sem, blandit pulvinar augue sit amet, auctor malesuada sapien. Nullam faucibus leo eget eros hendrerit, non laoreet ipsum lacinia. Curabitur cursus diam elit, non tempus ante volutpat a. Quisque hendrerit blandit purus non fringilla. Integer sit amet elit viverra ante dapibus semper. Vestibulum viverra rutrum enim, at luctus enim posuere eu. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Bananas
In this section, we provide some information about bananas.
Link to wikipedia: https://en.wikipedia.org/wiki/Banana
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sagittis posuere ligula sit amet lacinia. Duis dignissim pellentesque magna, rhoncus congue sapien finibus mollis. Ut eu sem laoreet, vehicula ipsum in, convallis erat. Vestibulum magna sem, blandit pulvinar augue sit amet, auctor malesuada sapien. Nullam faucibus leo eget eros hendrerit, non laoreet ipsum lacinia. Curabitur cursus diam elit, non tempus ante volutpat a. Quisque hendrerit blandit purus non fringilla. Integer sit amet elit viverra ante dapibus semper. Vestibulum viverra rutrum enim, at luctus enim posuere eu. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Oranges
In this section, we provide some information about oranges.
Link to wikipedia: https://en.wikipedia.org/wiki/Orange_(fruit)
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sagittis posuere ligula sit amet lacinia. Duis dignissim pellentesque magna, rhoncus congue sapien finibus mollis. Ut eu sem laoreet, vehicula ipsum in, convallis erat. Vestibulum magna sem, blandit pulvinar augue sit amet, auctor malesuada sapien. Nullam faucibus leo eget eros hendrerit, non laoreet ipsum lacinia. Curabitur cursus diam elit, non tempus ante volutpat a. Quisque hendrerit blandit purus non fringilla. Integer sit amet elit viverra ante dapibus semper. Vestibulum viverra rutrum enim, at luctus enim posuere eu. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Footnotes
so-called element-wise operations↩︎