Arithmetic on Whole Vectors
Lesson 3 of 8 · 11 min
One operation, every element
In most languages you would write a loop to double every price in a list. In R the arithmetic operators are vectorised: applied to a vector, they act on each element and return a vector of the same length. This is not a shortcut, it is the normal way to compute, and it is the reason R code for statistics is short.
prices <- c(4.5, 12, 7.25, 3) prices * 2 #> [1] 9.0 24.0 14.5 6.0 prices + 1 #> [1] 5.50 13.00 8.25 4.00 prices * 1.081 #> [1] 4.86450 12.97200 7.83725 3.24300 round(prices * 1.081, 2) #> [1] 4.86 12.97 7.84 3.24
Multiplying by 1.081 adds 8.1 percent tax to every price in one step. round() is vectorised too, so it rounds each of the four results. Mathematical functions behave the same way: sqrt(c(4, 9, 16)) returns 2 3 4.
Functions that reduce and functions that keep the length
It helps to sort functions into two families. Some keep the length, like the operators above: element in, element out. Others reduce a vector to one number: sum(), mean(), max(). Combining them is where the useful results come from. prices / sum(prices) divides each price by one number, the total, giving each item's share.
sum(prices) #> [1] 26.75 round(prices / sum(prices), 3) #> [1] 0.168 0.449 0.271 0.112 cumsum(prices) #> [1] 4.50 16.50 23.75 26.75 sqrt(c(4, 9, 16)) #> [1] 2 3 4
cumsum() is a third kind: it keeps the length but each element depends on all the ones before it, giving a running total. The shares sum to 1, and the last running total equals sum(prices); small checks like these tell you the computation did what you meant.
Two vectors of the same length
When both sides of an operator are vectors of equal length, R pairs them position by position: first with first, second with second, and so on. This is how you compute a difference between two measurements of the same units, or multiply a quantity vector by a price vector.
prices + c(1, 2, 3, 4) #> [1] 5.50 14.00 10.25 7.00
Recycling: what happens when lengths differ
prices * 2 already involved unequal lengths: four elements against one. R handled it by recycling, reusing the shorter vector from the start once it runs out. The same rule applies to any shorter vector, not only single numbers. With a two-element vector against four, the first is used for positions 1 and 3, the second for positions 2 and 4.
prices - c(0.5, 1) #> [1] 4.00 11.00 6.75 2.00 c(1, 2, 3) + c(10, 20) #> Warning in c(1, 2, 3) + c(10, 20): longer object length is not a multiple of shorter object length #> [1] 11 22 13
The second example shows the danger. Three against two does not divide evenly, so R warns, but it still returns an answer: 1 + 10, 2 + 20, and then 3 + 10 with the shorter vector restarted. The warning is the only sign that something is off, and the result is rarely what anyone intended. When the longer length is an exact multiple of the shorter one, there is no warning at all, which makes an accidental recycling of, say, a two-element vector against a ten-element one completely silent.
length() of both sides; usually one of them is not the vector you thought it was.c(10, 20, 30, 40) - c(1, 2) return?Sign in to answer and track your progress.
Sign in