mean(sqrt(sample(1:100, 10)))
# ... or slightly more human-readable form:
mean(
sqrt(
sample(1:100, 10)
) )
Bloody parentheses
1 The problems with parentheses
Functions take their input parameters enclosed in parentheses like e.g. mean(1:5)
.
Often, you will want to use the output of one function as the input for another function.
This leads to two common issues. Look at this simple example which picks a random sample of 10 numbers from the range of 1-to-100, calculates the square root of each number, and calculates the arithmetic mean:
Notice, two thing:
- you have 3 nested sets of parentheses - it is very easy loose track of how they pair up (or not).
- you code is actually executed top-down and left-to-right as
mean()
first andsample()
last. Themean()
function is executed first, but then pauses to wait until thesqrt()
function returns a result. Thesqrt()
function in turn will also pause and wait for the result of thesample()
function. In a sense therefor, the code is written left-to-right, but in reality completed in the order right-to-left. When designing the code, you sort of have to write your code backwards.
2 Help is at hand
2.1 Rainbow parentheses
Look into the menu Tools / Global Options / Code / Display / Use rainbow parentheses.
This option will color nested parentheses pairwise in different colors, making it easier to differentiate the matching parentheses.
Also notice, that when your cursor is placed immediately before a starting parentheses or immediate following a closing parenthesis, RStudio will highlight the corresponding parenthesis – note that this may not work as expected if there are missing or extra parantheses.
2.2 Use pipes
Many, but not all functions are pipe-friendly.
Using pipes, the example above can be written as:
sample(1:100,10) |> sqrt() |> mean()
In essence, the |>
pipe takes the output from the left-hand side and inserts it as (the first) input in the right hand side. Look at the slightly different example below:
sample(1:100,10) |> sqrt() |> mean(na.rm=TRUE)
We explicitly set the parameter na.rm
to TRUE
in the function mean()
. R will know to use the output of sqtr()
as the first input to mean()
(and only then, add the parameter na.rm
) … looking in the help file for mean()
, you can learn that the first parameter expected x
is data for which a mean can be calculated.
3 Problemer med parenteser
Funktioner tager deres inputparametre indkapslet i parenteser, som f.eks. mean(1:5)
.
Ofte vil du gerne bruge outputtet fra en funktion som input til en anden funktion.
Dette fører til to almindelige problemer. Se på dette enkle eksempel, der vælger en tilfældig stikprøve på 10 tal fra intervallet 1 til 100, beregner kvadratroden af hvert tal og dernæst beregner det aritmetiske gennemsnit:
mean(sqrt(sample(1:100, 10)))
# ... eller i en lidt mere læsbar form:
mean(
sqrt(
sample(1:100, 10)
) )
Bemærk to ting:
- Du har 3 indlejrede sæt parenteser – det er meget nemt at miste overblikket over, hvordan de parvis passer sammen (eller ikke gør).
- Din kode udføres faktisk fra top til bund og venstre mod højre, men rækkefølgen på udførelsen er
mean()
først ogsample()
sidst. Funktionenmean()
kaldes først, men venter på, atsqrt()
returnerer et resultat.sqrt()
venter så igen på resultatet frasample()
. På en måde skrives koden altså fra venstre mod højre, men den udføres i praksis fra højre mod venstre. Når du designer koden, skal du derfor nærmest skrive den baglæns.
4 Hjælp er inden for rækkevidde
4.1 Regnbueparenteser
Gå ind i menuen Værktøjer / Globale Indstillinger / Kode / Visning / Brug regnbueparenteser.
Denne mulighed vil farve indlejrede parenteser parvis i forskellige farver, hvilket gør det lettere at skelne mellem de matchende parenteser.
Bemærk også, at når din markør er placeret lige før en åbningsparentes eller lige efter en lukkende parentes, vil RStudio fremhæve (hvad den mener er) den tilsvarende parentes.
4.2 Brug pipes
Mange, men ikke alle funktioner er pipe-venlige.
Ved brug af pipes kan eksemplet ovenfor skrives som:
sample(1:100,10) |> sqrt() |> mean()
Essensen af |>
-pipen er, at den tager outputtet fra venstre side og indsætter det som (det første) input i højre side. Se på det lidt anderledes eksempel nedenfor:
sample(1:100,10) |> sqrt() |> mean(na.rm=TRUE)
Her sætter vi eksplicit parameteren na.rm
til TRUE
i funktionen mean()
. R ved, at outputtet fra sqrt()
skal bruges som det første input til mean()
(og derefter tilføjes parameteren na.rm
). Hvis du ser i hjælpesiden for mean()
, vil du opdage, at den første forventede parameter x
er data, som der kan beregnes et gennemsnit for.