Vectors: R thinks in rows of values
The vector is the one building block R is made of: how to build one, how to reach into it, and why arithmetic on a whole vector needs no loop.
One kind of value, many of them
A vector is a row of values of one kind: five numbers, or three names, or a run of whole numbers. c combines values into one, and it is the function you will type more than any other. Almost everything in R is a vector, including a single number, which is just a vector of length one. c also flattens what it is given: c(1, c(2, 3)) is still three values rather than a vector holding a vector, and a list is the structure that holds things of different shapes.
Three shortcuts build the patterns you need often. The colon makes a run: 1:6 is one, two, three, four, five, six. seq makes a run with a step you choose, as in seq(0, 10, by = 2). And rep repeats a value, as in rep("ha", 3).
Counting from one
Square brackets reach into a vector. scores[1] is the first value, and if that surprises you, you are in good company: R counts from one, not from zero, because it was written for people who count the way they talk.
The index can be more than one thing. scores[c(2, 4)] takes the second and fourth values, and scores[-1] takes everything except the first. length(scores) tells you how many there are, which is how you grab the last one without counting by hand. An index past the end answers NA rather than an error, which is why a loop that runs one step too far produces a missing value instead of stopping.
No loop needed
This is the idea that makes R feel different. scores + 5 adds five to every value of the vector at once. There is no loop in your code, because the loop is inside the language, written in a fast compiled layer rather than in interpreted R.
The same is true of the summary functions: sum, mean, min, max and median each take the whole vector and answer with one number. sort puts the values in order, and round trims a long decimal to something you can read. That rule also makes scores > 80 a vector of flags, and sum(scores > 80) the count of them, which is the pattern the next chapter leans on.
Building, indexing, summarising
scores <- c(72, 88, 95, 60, 88)
# Builders.
1:6
seq(0, 10, by = 2)
rep("ha", 3)
# Indexing, from one.
scores[1]
scores[length(scores)]
scores[-1]
scores[c(2, 4)]
# Whole-vector work.
scores + 5
sum(scores)
mean(scores)
sort(scores)One row of scores, asked five questions
Run it and check each line against the code above it. Then curve the scores by a different number, add a value of your own to the vector, and print the two middle values with a two-element index.
A vector printed on its own wraps across lines once it gets long, because R prints one line per row of output it can fit in eighty characters. Wrapping it in paste(x, collapse = " ") turns it into a single string, which is how every example in this course keeps its output to one line per idea.
When the lengths disagree
Arithmetic pairs values by position, but it does not require equal lengths. c(1, 2, 3, 4) + c(10, 20) reuses the shorter vector twice, giving 11, 22, 13, 24. This is called recycling, and for a clean multiple it is a feature: scores * c(1, -1) flips the sign of every pair.
When the lengths do not divide evenly R recycles anyway and adds a warning. The answer is usually meaningless, so treat that warning as an error. Checking length(a) == length(b) before the arithmetic is one line, and it catches the mistake at the point it was made.
Names, types and coercion
A vector can carry names, and then you can reach a value by name as well as by position: takings[["Fri"]]. names(x) reads the labels, names(x) <- ... sets them, and unname(x) strips them again. Names travel with the values through sorting and arithmetic, which is helpful until a printed result shows a label you had forgotten was there.
Every vector has one type. c(1, 2, "3") does not fail: R widens the whole vector to text, because a vector cannot hold a number in one slot and a string in the next. typeof(x) tells you what you actually have, and is.numeric(x) or is.character(x) answer the question you usually mean. as.numeric("42") converts when the text really is a number, and returns NA with a warning when it is not.
Three traps live in this chapter. scores[0] is an empty vector, not the first value, because counting starts at one. A negative index leaves values out, but mixing signs in one index — scores[c(-1, 2)] — is an error rather than a clever selection. And length counts values while nchar counts characters, so using one where you meant the other gives a number that looks plausible and is wrong.
Try these next
- Build the sequence 5, 10, 15, ..., 50 with
seq, then again with the colon and a multiplier. - Name a vector of three scores, then select one value by name and one by position and check they agree.
- Add a vector of length two to a vector of length six, then add one whose length does not divide evenly and read the warning.
A week of takings, labelled by day
Run it and check the best day against the numbers. Then change one day, predict how the total and the Saturday share move, and add a Sunday to both the vector and its names.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
What is scores[1] when scores is c(72, 88, 95)?
