[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
Etiam congue quam eget velit convallis, eu sagittis orci vestibulum. Vestibulum at massa turpis. Curabitur ornare ex sed purus vulputate, vitae porta augue rhoncus. Phasellus auctor suscipit purus, vel ultricies nunc. Nunc eleifend nulla ac purus volutpat, id fringilla felis aliquet. Duis vitae porttitor nibh, in rhoncus risus. Vestibulum a est vitae est tristique vehicula. Proin mollis justo id est tempus hendrerit. Praesent suscipit placerat congue. Aliquam eu elit gravida, consequat augue non, ultricies sapien. Nunc ultricies viverra ante, sit amet vehicula ante volutpat id. Etiam tempus purus vitae tellus mollis viverra. Donec at ornare mauris. Aliquam sodales hendrerit ornare. Suspendisse accumsan lacinia sapien, sit amet imperdiet dui molestie ut.
Bananas
In this section, we provide some information about bananas.
Link to wikipedia: https://en.wikipedia.org/wiki/Banana
Etiam non efficitur urna, quis elementum nisi. Mauris posuere a augue vel gravida. Praesent luctus erat et ex iaculis interdum. Nulla vestibulum quam ac nunc consequat vulputate. Nullam iaculis lobortis sem sit amet fringilla. Aliquam semper, metus ut blandit semper, nulla velit fermentum sapien, fermentum ultrices dolor sapien sed leo. Vestibulum molestie faucibus magna, at feugiat nulla ullamcorper a. Aliquam erat volutpat. Praesent scelerisque magna a justo maximus, sit amet suscipit mauris tempor. Nulla nec dolor eget ipsum pellentesque lobortis a in ipsum. Morbi turpis turpis, fringilla a eleifend maximus, viverra nec neque. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
Oranges
In this section, we provide some information about oranges.
Link to wikipedia: https://en.wikipedia.org/wiki/Orange_(fruit)
Praesent ornare dolor turpis, sed tincidunt nisl pretium eget. Curabitur sed iaculis ex, vitae tristique sapien. Quisque nec ex dolor. Quisque ut nisl a libero egestas molestie. Nulla vel porta nulla. Phasellus id pretium arcu. Etiam sed mi pellentesque nibh scelerisque elementum sed at urna. Ut congue molestie nibh, sit amet pretium ligula consectetur eu. Integer consectetur augue justo, at placerat erat posuere at. Ut elementum urna lectus, vitae bibendum neque pulvinar quis. Suspendisse vulputate cursus eros id maximus. Duis pulvinar facilisis massa, et condimentum est viverra congue. Curabitur ornare convallis nisl. Morbi dictum scelerisque turpis quis pellentesque. Etiam lectus risus, luctus lobortis risus ut, rutrum vulputate justo. Nulla facilisi.
Footnotes
so-called element-wise operations↩︎