4  Vectors

Vectors are sequences of numbers. The notation for vectors is not always applied consistently, but often vectors are topped with an arrow (or are bold lowercase letters), and the elements are listed in parentheses and separated by commas. A vector \vec{x} with elements 4 and 3 would be notated like so:

A vector is an ordered sequence of values.

\vec{x}=\left(4,3\right)

The vector length refers to how many elements it has, not its magnitude. So a 2-element vector like (x_1,x_2) has a length of 2.

A vector’s length is the number of elements the vector contains.

A sequence of indeterminate length n, would be notated like so

\vec{x}=\left(x_1,x_2,\ldots,x_n\right)

4.1 Making vectors in R

R is a peculiar peculiar language in that almost every object created in R is ultimately a vector of some kind or another. Here we are concerned with vectors made with real numbers (i.e., positive and negative numbers that can have decimals).

R can create vectors from many other types of data (e.g., integers, complex numbers, logical values, text, and raw binary numbers). A more advanced discussion about vectors in R can be found here.

4.1.1 Making vectors with the c function

Vectors in R are created in many ways, but the most common way to join vector elements is with the c function. The c function “combines” (or concatenates) elements into a vector. For example, to combine 3 and 5:

To concatenate is to link things together in a chain or series.
x <- c(3, 5)
You Try

Create a vector x with values 2 and 6.

Suggested Solution
x <- c(2, 6)

4.1.2 Making vector sequences with the : operator

You can make sequential integer sequences with the : operator. To make a sequence from 1 to 5:

1:5
[1] 1 2 3 4 5

To make a decreasing vector from 4 to 0:

4:0
[1] 4 3 2 1 0
You Try

Create a sequence of integers from 5 to 11 with the : operator.

Suggested Solution
5:11
[1]  5  6  7  8  9 10 11

4.1.3 Making vector sequences with seq function

The seq function allows for sequences of any interval or length.

seq(1,5)
[1] 1 2 3 4 5

Decreasing from 5 to 1:

seq(5,1)
[1] 5 4 3 2 1

The by argument specifies the interval between elements. Here we specify a sequence from 0 to 1 by .1 intervals:

seq(0, 1, 0.1)
 [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0

For decreasing sequences, the by argument needs to be negative:

seq(5, 3, -0.5)
[1] 5.0 4.5 4.0 3.5 3.0
You Try

Create a sequence of integers from 3 to 6 with the seq function.

Suggested Solution
seq(3, 6)
[1] 3 4 5 6

Create a sequence of even integers from 2 to 10 with the seq function.

Suggested Solution
seq(2, 10, 2)
[1]  2  4  6  8 10

Create a decreasing sequence of integers from 6 to 3 with the seq function.

Suggested Solution
seq(6, 3)
[1] 6 5 4 3

Create a decreasing sequence of numbers from 1 to -1 decreasing by increments of 0.2.

Suggested Solution
seq(1, -1, -0.2)
 [1]  1.0  0.8  0.6  0.4  0.2  0.0 -0.2 -0.4 -0.6 -0.8 -1.0

4.2 Selecting Specific Elements in a Vector

In R, there are several ways to select elements in a vector—by position, by condition, and by name.

4.2.1 Selecting by Position

Suppose we have a vector with 5 elements:

\vec{x}=\left(10,20,30,40,50\right)

First I define \vec{x}

x <- seq(10, 50, 10)
x
[1] 10 20 30 40 50

The 3rd element, 30, can be selected like so:

x[3]
[1] 30
You Try

Select the 4th element of x.

Suggested Solution
x[4]
[1] 40

If I want both the 3rd and 5th elements, I use a vector inside the square brackets:

x[c(3, 5)]
[1] 30 50
You Try

Select first and fourth element of x.

Suggested Solution
x[c(1, 4)]
[1] 10 40

4.2.2 Selecting by Condition

R can select elements meeting any condition that evaluates to the logical value of TRUE. For example, which values of \vec{x} are greater than 35?

x > 35
[1] FALSE FALSE FALSE  TRUE  TRUE

This creates a vector of 5 elements that are either TRUE or FALSE. We can select just the elements for which the condition is TRUE like so:

x[x > 35]
[1] 40 50
You Try

Select elements of x less than 15.

Suggested Solution
x[x < 15]
[1] 10

4.2.3 Selecting by Name

In R, vector elements can have names. We can assign them directly like this:

x <- c(a = 1, b = 2, c = 3, d = 4, e = 5)
x
a b c d e 
1 2 3 4 5 

We can also assign names using the names function:

x <- 1:5
x_names <- c("a", "b", "c", "d", "e")
names(x) <- x_names
x
a b c d e 
1 2 3 4 5 

We can select specific named elements like so:

x[c("a", "d")]
a d 
1 4 

We can select them in any order:

x[c("d", "a")]
d a 
4 1 

We can even have repeats:

x[c("a", "a", "b")]
a a b 
1 1 2 
You Try

Select elements b and a of x, in that order .

Suggested Solution
x[c("b", "a")]
b a 
2 1 

4.3 Scalar–Vector Operations

When a scalar and a vector appear together in an operation, the operation is applied to the scalar and to every element in the vector.

4.3.1 Scalar–Vector Multiplication

To multiply a scalar by a vector, multiply every element in the vector by the scalar. If a is a scalar,

a\vec{x}=\left(ax_1, ax_2,\ldots, ax_n\right)

They are called “scalars” because a scalar multiplied by a vector “scales” the vector by changing its magnitude.

\left\|a\vec{x}\right\|=a\left\|\vec{x}\right\|

You can play with scalar multiplication with the web app in Figure 12.2. Set the x and y coordinates for the blue vector, and alter the scalar a to see how the red vector’s magnitude changes. When a is negative, the red vector reverses direction.

4.3.2 Scalar–Vector Division

Scalar-vector division looks just like it does in regular algebra and can take on a variety of forms:

\vec{x}/a=\frac{\vec{x}}{a}=\frac{1}{a}\vec{x}=a^{-1}\vec{x}=\vec{x}\div a

4.3.3 Scalar-Vector Addition

Scalar–vector addition works in similar fashion. To add scalar to a vector:

\vec{x}-a=\left(x_1+a,x_2+a,\ldots,x_n+a\right)

That is, the scalar is added to every value of the vector.

4.3.4 Scalar-Vector Subtraction

To subtract:

\vec{x}-a=\left(x_1-a, x_2-a,\ldots,x_n-a\right)

4.3.5 Scalar-Vector Operations in R

In R, almost everything—even things that look like scalars—are really vectors. When a scalar (i.e., a vector of length 1) and a longer vector are added, subtracted, multiplied, or divided, the scalar is “recycled” across all the values of longer vector. This is also true when a short vector (e.g., of length 2) is added to a longer vector (e.g., of length 4): the shorter vector is recycled across the longer vector. For example, c(1,2) + c(1,2,3,4) will return 2 4 4 6

Scalar-vector operations look just alike scalar-scalar operations:

x <- c(1,2)
x + 5
[1] 6 7
x - 1
[1] 0 1
x * 4
[1] 4 8
x / 2
[1] 0.5 1.0

4.4 Vector Addition and Subtraction

To add two vectors, add each element at the same position:

\begin{aligned} \vec{x}&= \left(x_1,x_2,\ldots,x_n\right)\\ \vec{y}&= \left(y_1,y_2,\ldots,y_n\right)\\ \vec{x}+\vec{y}&= \left(x_1+y_1,x_2+y_2,\ldots,x_n+y_n\right)\\ \end{aligned}

As an example:

\begin{aligned} \vec{x}&= \left(1,2\right)\\ \vec{y}&= \left(3,4\right)\\ \\ \vec{x}+\vec{y}&= \left(1+3,2+4\right)\\ &= \left(4,6\right) \end{aligned}

Vector subtraction works the same way as vector addition, subtracting each element at the same position:

\vec{x}-\vec{y}= \left(x_1-y_1,x_2-y_2,\ldots,x_n-y_n\right)

Adding and subtracting two vectors is only defined when the vectors have the same number of elements. Thus, if \vec{x}= \left(1,2\right) and \vec{y}= \left(3,2,1\right), there is no defined way to add \vec{x} and \vec{y}.

In R, adding and subtracting vectors is beautifully easy. Unlike many programming language, we do not need to create looping structures to add each element pair one at a time. We just define the vectors and add them:

x <- c(1, 2)
y <- c(3, 4)
x + y
[1] 4 6
You Try

If vector \vec{a} is (5, 6) and vector \vec{b} is (10, 1), what is the sum of \vec{a} and \vec{b}? Use R to compute your answer.

Suggested Solution
a <- c(5, 6)
b <- c(10, 1)
a + b
[1] 15  7
Figure 4.1: A vector of (4, 3) moves 4 units to the right and 3 units up from the origin.

A vector with two scalar elements can be thought of as an arrow in a coordinate plane, as in Figure 4.1. The vector \left(4, 3\right) is an arrow that displaces any point it is added to by 4 units to the right and 3 units up.

middle_axes <- function(limits = c(0, 5)) {
  breaks <- seq(limits[1], limits[2])
  breaks <- breaks[breaks != 0]
  ggplot() +
    theme_classic(
    base_family = bfont,
    base_size = 18,
    base_line_size = .5
  ) +
  theme(
    axis.text = element_text(color = "gray40"),
    axis.line = element_blank(),
    axis.ticks = element_line(color = "gray"),
    axis.title.x = element_text(
      angle = 0,
      vjust = .5,
      face = "italic",
      color = "gray40"
    ),
    axis.title.y = element_text(
      angle = 0,
      vjust = .5,
      face = "italic",
      color = "gray40"
    )
  ) +
  scale_x_continuous(name = "y", 
                     breaks = breaks, 
                     labels = WJSmisc::signs_centered) +
  scale_y_continuous(name = "x", 
                     breaks = breaks, 
                     labels = signs) +
  ggh4x::coord_axes_inside(
    xlim = limits,
    ylim = limits,
    labels_inside = T,
    ratio = 1
  ) +
  ob_segment(x = c(0, limits[1] - abs(max(limits) - min(limits)) / 20), 
             xend = c(0, limits[2] + abs(max(limits) - min(limits)) / 20), 
             y = c(limits[1] - abs(max(limits) - min(limits)) / 20, 0), 
             yend = c(limits[2] + abs(max(limits) - min(limits)) / 20, 0), 
             linewidth = .75, 
             arrow_head = my_arrowhead, 
             arrow_fins = my_arrowhead, 
             color = "gray")
}

o <- ob_point(0,0, color = myfills[1])
p <- ob_point(x_plot, y_plot, color = myfills[1])

middle_axes() +
  p  + 
  ob_latex(tex = paste0("\\vec{v}=", p@auto_label),
           center = p + ob_point(.1,.14),
           color = myfills[1],height = .2) +
  ob_segment(o, p, 
             resect_head = 1.5, 
             arrow_head = my_arrowhead, 
             color = myfills[1], 
             vjust = 0, 
             label = ob_label(
               paste0("Magnitude of **v**: \u2016**v**\u2016 = ", 
                      round(p@r,2)),
               size = 18)) 
Figure 4.2: Vector addition

In Figure 12.1, you can play with vector addition.

4.4.1 Vector Norms

If we visualize a vector as an arrow, we can ask how long the arrow is from end to end. The norm is the vector’s magnitude. Imagine the vector’s n elements plotted as a single point in n-dimensional space. The norm is the distance of the point to the origin (i.e., a vector of n zeroes). The distance referred to here is technically the Euclidean distance, which is a generalization of the Pythagorean Theorem to more than 2 dimensions. To calculate it, take the square root of the sum of all squared values in the vector.

A vector’s norm is the Euclidean distance of the vector’s n elements to the origin in n-dimensional space.

Vector norms sometimes have notation that can be confused with absolute values:

\left|\vec{x}\right|

The notational confusion is not accidental. Scalar absolute values and vector norms both refer to magnitude. Indeed, if you apply the formula for vector norms to a vector with one element, the result is the absolute value:

\sqrt{x_1^2} = |x_1|

However, to avoid the ambiguity between vector norms and taking the absolute value of each element, I will use the double bar notation:

\left\|\vec{x}\right\|

I tend to be fastidious about distinguishing between vector length (the number of elements in a vector) and vector norms (the vector’s magnitude) because the concepts are easily confused. Further confusion is that the norm of a vector is not the same thing as a normal vector, which is a vector that is perpendicular to a surface (e.g., a plane, a sphere, or any other multidimensional object) at a given point. A normal vector has nothing to do with the normal distribution.

\left\|\vec{x}\right\|=\sqrt{x_1^2+x_2^2+\ldots+x_n^2}

To calculate a vector norm in R by hand is straightforward:

x <- c(4, 3)
sqrt(sum(x ^ 2))
[1] 5

If you can remember that this kind of norm (there are others) is a “type 2” norm, then a vector norm can be calculated with the norm function:

norm(x, type = "2")
[1] 5

4.4.2 Unit Vectors

A vector norm is useful for creating unit vectors, which have the same direction as the original vector but have a norm (i.e, magnitude) of 1.

A unit vector \vec{u} has a norm of 1: \left\|\vec{u}\right\|=1

So a unit vector \vec{u} that has the same direction as vector \vec{x} = \left(3,4\right) is:

\begin{align*} \vec{u}&=\frac{\vec{x}}{\left\|\vec{x}\right\|}\\ &=\frac{\left(3,4\right)}{\sqrt{3^2+4^2}}\\ &=\frac{\left(3,4\right)}{5}\\ &=\left(.6,.8\right) \end{align*}

We can verify that \vec{u} has a norm of 1:

\begin{align*} \left\|\vec{u}\right\|&=\left\|\left(.6,.8\right)\right\|\\ &=\sqrt{.6^2+.8^2}\\ &=1 \end{align*}

Unit vectors have many uses, including the calculation of correlation coefficients.

4.4.3 Vector Multiplication

There are several different ways that vectors can be multiplied. For now, the most important are element-wise multiplication and dot-product multiplication.

4.4.3.1 Element-wise Multiplication (\circ)

This kind of multiplication is analogous to vector addition and subtraction. If two vectors have the same length (i.e, number of elements), element-wise multiplication creates a vector of the same length by multiplying each element. Thus,

\begin{aligned} \vec{x}&= \left(x_1,x_2,\ldots,x_n\right)\\ \vec{y}&= \left(y_1,y_2,\ldots,y_n\right)\\ \vec{x}\circ \vec{y}&= \left(x_1y_1,x_2 y_2,\ldots,x_n y_n\right)\\ \end{aligned}

In R, element-wise multiplication is straightforward. Just multiply the vectors with the * operator.

x <- c(1, 2, 3)
y <- c(2, 4, 6)
x * y
[1]  2  8 18

4.4.3.2 Dot-Product Multiplication (\cdot)

This is the same as element-wise multiplication, but the products are added together to create a scalar.

\begin{aligned} \vec{x}&= \left(x_1,x_2,\ldots,x_n\right)\\ \vec{y}&= \left(y_1,y_2,\ldots,y_n\right)\\ \vec{x}\cdot \vec{y}&= x_1 y_1+x_2 y_2+\ldots+x_n y_n\\ \end{aligned}

If \vec{x}=(1,2) and \vec{y}=(3,4),

\begin{aligned} \vec{x} \cdot \vec{y}&=1\cdot 3+2\cdot 4\\ &=3+8\\ &=11 \end{aligned}

As will be seen later, the dot-product of 2 vectors is performed in R with the same operator as matrix multiplication: %*%.

x <- c(1, 2)
y <- c(3, 4)
x %*% y
     [,1]
[1,]   11

However, if this is hard to remember, then the dot product can thought of as “the sum of the elements multiplied” like so:

sum(x * y)
[1] 11

I was surprised to learn that in matrix algebra dot-product multiplication is much more often used than element-wise multiplication. Indeed, matrix multiplication consists of many dot-product multiplications. Apart from that, dot-product multiplication has a number of important applications related to the Law of Cosines, finding orthogonal vectors (i.e., vectors at right angles), and the geometric interpretation of correlation coefficients. I will leave those topics for later.