3  Vectors

3.1 Quiz

More details are available in the Vectors Quiz book chapter.

3.1.1 Quiz 1

What are the four common types of atomic vectors? What are the two rare types?

Answers

The 4 common types are logical, double, integer, and character

The 2 rare types are complex (depicting complex numbers) and raw (binary data, displayed as hex values).

3.1.2 Quiz 2

What are attributes? How do you get them and set them?

Answers

Attributes are metadata attached to atomic vectors to create more complex data structures from them. For example, dim turns a vector into a matrix, names gives each vector elements a name.

For example:

3.1.3 Quiz 3

How is a list different from an atomic vector? How is a matrix different from a data frame?

Answers

  • A list is a vector of references to objects. These objects can be vectors that contain data. Lists don’t contain actual “data”.

  • A matrix is an atomic vector with a dim attribute. A data frame is a list of atomic vectors. All data in a matrix must be the same type, where each column in a data frame may have a different type.

3.1.4 Quiz 4

Can you have a list that is a matrix? Can a data frame have a column that is a matrix?

Answers

List that is a matrix: By assigning dimensions to a list:

Matrix as a column of a dataframe: By assigning (making sure there are enough rows):

3.1.5 Quiz 5

How do tibbles behave differently from data frames?

Answers

They don’t coerce strings to factors, print more nicely, and has more robust subsetting.

3.2 Atomic vectors

More details are available in the Atomic vectors book chapter.

3.2.1 Ex. 1

How do you create raw and complex scalars? (See ?raw and ?complex.)

Answers

There are many ways to create raw vectors:

  • Directly create a vector containing as.raw data.
  • Create a vector, then coerce it to raw using as.raw().
  • Create an empty raw vector then fill slots.

There are also many ways to create complex vectors:

  • Directly create a vector containing complex data.
  • Create a vector, then coerce it to complex using as.complex(). However, the data won’t have an imaginary part.
  • Create an empty complex vector then fill slots.

3.2.2 Ex. 2

Test your knowledge of the vector coercion rules by predicting the output of the following uses of c():

Answers

In order, these vectors will be coerced to their most basic type: - Coerced to double - Coerced to character - Coerced to integer

3.2.3 Ex. 3

Why is 1 == "1" true? Why is -1 < FALSE true? Why is "one" < 2 false?

Answers

Because both sides of the argument are coerced (in the order of logical -> numeric -> character) prior to comparison.

3.2.4 Ex. 4

Why is the default missing value, NA, a logical vector? What’s special about logical vectors? (Hint: think about c(FALSE, NA_character_).)

Answers

Of the multiple types of logicals, NA is automatically set to the strictest type possible, allowing it to be coerced following the rest of the vector. Where coercion is not needed, it defaults to the strictest type of logical.

3.2.5 Ex. 5

Precisely what do is.atomic(), is.numeric(), and is.vector() test for?

Answers

  • is.atomic() checks whether the object is an atomic vector (falling into 6 defined classes and direct extensions)
  • is.numeric() checks whether the data is intepretable as numbers (base type double or integer)
  • is.vector() checks whether the provided vector (includes list) have no attributes other than names. Since a matrix is a vector with the dim attribute, it would fail this test.

3.3 Attributes

More details are available in the Attributes book chapter.

3.3.1 Ex. 1

How is setNames()implemented? How is unname() implemented? Read the source code.

Answers

setNames is simply an inline version of the names attribute setter function.

unname() is more complicated. - If the object has a names attribute, set it to NULL - If the object has a dimnames attribute, is a dataframe, and force is TRUE set it to NULL

3.3.2 Ex. 2

What does dim() return when applied to a 1-dimensional vector? When might you use NROW() or NCOL()?

Answers

dim() returns NULL when applied to a 1-dimensional vector.

NROW() and NCOL() are applied to objects feasibly treated as 2-dimensional, such as vectors, matrix, dataframe. Difference between nrow() and NROW() is that NROW() treats vectors as a matrix with one column.

The length of the 1st dimension is the number of rows, the length of the 2nd dimension is the number of columns.

3.3.3 Ex. 3

How would you describe the following three objects? What makes them different from 1:5?

Answers

  • x1 is a 3D array with 1 row, 1 column, and 5 third-dimensional length
  • x2 is a 3D array with 1 row, 5 columns, and 1 third-dimensional length
  • x3 is a 3D array with 5 row, 1 columns, and 1 third-dimensional length

They are 3-dimensional objects with a dim attribute, whereas 1:5 does not.

3.3.4 Ex. 4

An early draft used this code to illustrate structure():

But when you print that object you don’t see the comment attribute. Why? Is the attribute missing, or is there something else special about it?

Answers

By default, the comment attribute is not printed. See ?comment

3.4 S3 atomic vectors

More details are available in the S3 atomic vectors book chapter.

3.4.1 Ex. 1

What sort of object does table() return? What is its type? What attributes does it have? How does the dimensionality change as you tabulate more variables?

Answers

table() returns a contingency table (technically an array) detailing the counts of each combinations of a factor or vector. Number of array dimensions increase as the number of variables in the contingency table increases.

3.4.2 Ex. 2

What happens to a factor when you modify its levels?

Answers

The underlying integer vector is unchanged, but the reversed levels attribute cause the factor to be reversed. In effect, the data is changed. So don’t use rev() for this purpose…

3.4.3 Ex. 3

What does this code do? How do f2 and f3 differ from f1?

Answers

  • f1: The underlying integer vector is maintained, but the factors are reversed, leading to modification of data.

  • f2: The underlying integer vector is reversed, the factors are not. This represents a modification of the data.

  • f3: The underlying integer vector is reversed, the factors are also reversed. Hence, the data is (in effect) unchanged.

3.5 Lists

More details are available in the Lists book chapter.

3.5.1 Ex. 1

List all the ways that a list differs from an atomic vector.

Answers

  • A list object does not itself contain data, only references to data objects.
  • A list can contain multiple object types, even other lists. This recursiveness makes them different from vectors

3.5.2 Ex. 2

Why do you need to use unlist() to convert a list to an atomic vector? Why doesn’t as.vector() work?

Answers

A list can contain lists or other objects that do not fit inside an atomic vector. unlist() has extra logic to handle this, as.vector() doesn’t.

3.5.3 Ex. 3

Compare and contrast c() and unlist() when combining a date and date-time into a single vector.

Answers

3.6 Data frames and tibbles

More details are available in the Data frames and tibbles book chapter.

3.6.1 Ex. 1

Can you have a data frame with zero rows? What about zero columns?

Answers

Yes and yes, a dataframe can have no rows and columns. This can also occur via subsetting of dataframes.

3.6.2 Ex. 2

What happens if you attempt to set rownames that are not unique?

Answers

With the case of dataframes, an error is given, since each row is meant to represent an unique sample.

3.6.3 Ex. 3

If df is a data frame, what can you say about t(df), and t(t(df))? Perform some experiments, making sure to try different column types.

Answers

First, the dataframe is coerced to a matrix. At this step, all values are coerced to the same type.

3.6.4 Ex. 4

What does as.matrix() do when applied to a data frame with columns of different types? How does it differ from data.matrix()?

Answers

In summary, as.matrix() coerces dataframes to characters, data.matrix() coerces dataframes to numeric.