# TRUE becomes 1 so 1 + 5 = 6
TRUE + 5 [1] 6
# FALSE becomes 0 so 0 + 5 = 5
FALSE + 5 [1] 5
# 1 + 0 + 1 = 2
v <- c(TRUE, FALSE, TRUE)
sum(v) [1] 2
From R Coding Basics: An Introduction to the Basics of Coding in R by Dr. Gaston Sanchez:
Implicit and explicit coercion
Vectorization and recycling
Working with logical vectors
Subsetting: numeric and logical indexing
Useful functions for vectors
Broadly speaking, implicit coercion is how R decides what type the output should be when combining or performing operations on different atomic types.
Implicit coercion is most commonly found in calculations with logical values and in vector creation using the combine c() function.
# TRUE becomes 1 so 1 + 5 = 6
TRUE + 5 [1] 6
# FALSE becomes 0 so 0 + 5 = 5
FALSE + 5 [1] 5
# 1 + 0 + 1 = 2
v <- c(TRUE, FALSE, TRUE)
sum(v) [1] 2
💻 Hands-On
Guess the output in the following R code. Try the code to confirm your guess.
TRUE * 2
FALSE * 2
v1 <- c(TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE)
sum(v1)
v2 <- c(F, T, F, F, T, F, T)
sum(v2)# TRUE becomes 1 so 1 * 2 = 2
TRUE * 2[1] 2
# FALSE becomes 0 so 0 * 2 = 0
FALSE * 2[1] 0
# 1 + 1 + 0 + 0 + 1 + 0 + 0 = 3
v1 <- c(TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE)
sum(v1)[1] 3
# 0 + 1 + 0 + 0 + 1 + 0 + 1 = 3
v2 <- c(F, T, F, F, T, F, T)
sum(v2)[1] 3
c()Implicit coercion also occurs when we combine different atomic types into a single vector.
In this case, all elements are converted to the most complex type (character).
\[ \text{Character} \, > \, \text{Double} \, > \, \text{Integer} \, > \, \text{Logical} \]
# integer > logical
c(4L, TRUE, TRUE, FALSE) [1] 4 1 1 0
# double > integer > logical
c(7.3, 4L, TRUE, TRUE, FALSE) [1] 7.3 4.0 1.0 1.0 0.0
# character > double > integer > logical
c("eagles", 7.3, 4L, TRUE, TRUE, FALSE) [1] "eagles" "7.3" "4" "TRUE" "TRUE" "FALSE"
💻 Hands-On
Guess the output in the following R code. Try the code to confirm your guess.
v1 <- c(TRUE, 3.5, FALSE, 1L)
sum(v1)
v2 <- c(FALSE, TRUE, 2, 3, "4", 5L)
sum(v2)# Coercion gives c(1.0, 3.5, 0.0, 1.0)
v1 <- c(TRUE, 3.5, FALSE, 1L)
sum(v1)[1] 5.5
# Coercion gives c("FALSE", "TRUE", "2", "3", "4", "5") so sum() gives an error
v2 <- c(FALSE, TRUE, 2, 3, "4", 5L)
sum(v2)Error in sum(v2): invalid 'type' (character) of argument
as.logical() # to logical type
as.integer() # to integer type
as.double() # to double type
as.numeric() # to numeric type
as.character() # to character typeIn R, vectorization means when we apply a function or operation on a vector, it will be done element by element automatically.
This means we do not need to loop through the vector.
# x: 4 8 25 49
# sqrt(x): sqrt(4) sqrt(8) sqrt(25) sqrt(49)
# output: 2 3 5 7
x <- c(4, 9, 25, 49)
sqrt(x)[1] 2 3 5 7
# x: 1 2 3 4
# + + + +
# y: 3 5 6 2
# output: 4 7 9 6
x <- c(1, 2, 3, 4)
y <- c(3, 5, 6, 2)
x + y[1] 4 7 9 6
💻 Hands-On
Verify the properties of vectorization with the following code
x <- c(1, 2, 3, 4)
y <- c(3, 5, 6, 2)
x - y
x * y
y / x
log(y)
sin(x)Due to vectorization, R will perform operations on corresponding elements.
x <- c(1, 2, 3, 4)
y <- c(3, 5, 6, 2)See the following
x - y[1] -2 -3 -3 2
x * y[1] 3 10 18 8
y / x[1] 3.0 2.5 2.0 0.5
log(y)[1] 1.0986123 1.6094379 1.7917595 0.6931472
sin(x)[1] 0.8414710 0.9092974 0.1411200 -0.7568025
# x: 1 2 3 4
# * * * *
# 2 2 2 2
# output: 2 4 6 8
x <- c(1, 2, 3, 4)
x * 2[1] 2 4 6 8
💻 Hands-On
Try the following R code and see what it returns. What do you think this sneaky code does?
# Please avoid!
x <- c(5, 3, 7, 4, 6, 8, 3)
y <- c(1, 2)
x + yWe will see the followling
x <- c(5, 3, 7, 4, 6, 8, 3)
y <- c(1, 2)
x + y[1] 6 5 8 6 7 10 4
The shorter vector y recycles its elements to match the length of the longer vector x. The above is equivalent to
x <- c(5, 3, 7, 4, 6, 8, 3)
y <- c(1, 2, 1, 2, 1, 2, 1)
x + y[1] 6 5 8 6 7 10 4
# logical vector
c(TRUE, FALSE, FALSE, TRUE, TRUE)
c(T, F, F, T, T)| Logical Operator | Description |
< |
Less than |
<= |
Less than or equal to |
> |
Greater than |
>= |
Greater than or equal to |
== |
Exactly equal to |
!= |
Not equal to |
x <- c(-2, -1, 0, 1, 2, 3)
# less than
x < 0
# less than or equal to
x <= 0
# greater than
x > 0
# greater than or equal to
x >= 0
# exactly equal to
x == 0
# not equal to
x != 0 💻 Hands-On
Consider daily high temperatures in celsius over two weeks. Write R code to answer the following questions:
Which days had temperatures at least 30°C?
Which days had temperatures exactly equal to 19°C?
Which days had temperatures below 20°C?
Which days had temperatures greater than 25°C?
Which days had temperatures at most 22°C?
# Daily high temperatures over two weeks
temps <- c(
Mon02 = 18, Tue03 = 21, Wed04 = 19, Thu05 = 25, Fri06 = 27, Sat07 = 30, Sun08 = 22,
Mon09 = 20, Tue10 = 16, Wed11 = 24, Thu12 = 28, Fri13 = 31, Sat14 = 29, Sun15 = 17
)Here, we will create logical vectors and use TRUE values to tell which days satisfy the conditions. Note that the vector temps has names to make it easier to tell.
temps >= 30Mon02 Tue03 Wed04 Thu05 Fri06 Sat07 Sun08 Mon09 Tue10 Wed11 Thu12 Fri13 Sat14
FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
Sun15
FALSE
temps == 19Mon02 Tue03 Wed04 Thu05 Fri06 Sat07 Sun08 Mon09 Tue10 Wed11 Thu12 Fri13 Sat14
FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
Sun15
FALSE
temps < 20Mon02 Tue03 Wed04 Thu05 Fri06 Sat07 Sun08 Mon09 Tue10 Wed11 Thu12 Fri13 Sat14
TRUE FALSE TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
Sun15
TRUE
temps > 25Mon02 Tue03 Wed04 Thu05 Fri06 Sat07 Sun08 Mon09 Tue10 Wed11 Thu12 Fri13 Sat14
FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE TRUE TRUE TRUE
Sun15
FALSE
temps <= 22Mon02 Tue03 Wed04 Thu05 Fri06 Sat07 Sun08 Mon09 Tue10 Wed11 Thu12 Fri13 Sat14
TRUE TRUE TRUE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE
Sun15
TRUE
sum() functionApplying the sum() function to a logical vector gives the number of TRUE values.
Recall that implicit coercion turns logical values to \(1\)’s and \(0\)’s.
# 1 + 0 + 0 + 1 + 1
v <- c(TRUE, FALSE, FALSE, TRUE, TRUE)
sum(v)[1] 3
💻 Hands-On
Consider the following vector
x <- c(-2, -1, 0, 1, 2, 3)Try the following R code and see what it returns.
sum(x < 0)
sum(x <= 0)
sum(x > 0)
sum(x >= 0)
sum(x == 0)
sum(x != 0)sum(x < 0)[1] 2
sum(x <= 0)[1] 3
sum(x > 0)[1] 3
sum(x >= 0)[1] 4
sum(x == 0)[1] 1
sum(x != 0)[1] 5
💻 Hands-On
Consider daily high temperatures in celsius over two weeks. Write R code to answer the following questions:
How many days had temperatures below 18°C?
How many days had temperatures greater than 26°C?
How many days had temperatures at most 21°C?
How many days had temperatures at least 28°C?
# Daily high temperatures over two weeks
temps <- c(
Mon02 = 18, Tue03 = 21, Wed04 = 19, Thu05 = 25, Fri06 = 27, Sat07 = 30, Sun08 = 22,
Mon09 = 20, Tue10 = 16, Wed11 = 24, Thu12 = 28, Fri13 = 31, Sat14 = 29, Sun15 = 17
)sum(temps < 18)[1] 2
sum(temps > 26)[1] 5
sum(temps <= 21)[1] 6
sum(temps >= 28)[1] 4
which() functionwhich() function returns the indices of TRUE values.💻 Hands-On
Consider the following vector
x <- c(-2, -1, 0, 1, 2, 3)Try the following R code and see what it returns.
which(x < 0)
which(x > 0)
which(x <= 0)
which(x >= 0)
which(x == 0)
which(x != 0)which(x < 0)[1] 1 2
which(x > 0)[1] 4 5 6
which(x <= 0)[1] 1 2 3
which(x >= 0)[1] 3 4 5 6
which(x == 0)[1] 3
which(x != 0)[1] 1 2 4 5 6
| Relationship Operator | Description |
| & | and |
| | | or |
| ! | not |
💻 Hands-On
Consider the following vector
x <- c(1, 2, 3, 4, 5, 6, 7, 8, 9)Try the following R code and see what it returns.
x > 3 & x < 8
!(x > 3 & x < 8)# 3 < x < 8
x > 3 & x < 8[1] FALSE FALSE FALSE TRUE TRUE TRUE TRUE FALSE FALSE
# Opposite of 3 < x < 8
!(x > 3 & x < 8)[1] TRUE TRUE TRUE FALSE FALSE FALSE FALSE TRUE TRUE
💻 Hands-On
Consider the following vector
x <- c(1, 2, 3, 4, 5, 6, 7, 8, 9)Try the following R code and see what it returns.
x < 4 | x > 6
!(x < 4 | x > 6)# x < 4 or x > 6
x < 4 | x > 6[1] TRUE TRUE TRUE FALSE FALSE FALSE TRUE TRUE TRUE
# Opposite of x < 4 or x > 6
!(x < 4 | x > 6)[1] FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
💻 Hands-On
Consider daily high temperatures in celsius over two weeks. Write R code to answer the following questions:
Which days had temperatures at least 20°C and at most 25°C?
Which days had temperatures below 18°C or above 28°C?
# Daily high temperatures over two weeks
temps <- c(
Mon02 = 18, Tue03 = 21, Wed04 = 19, Thu05 = 25, Fri06 = 27, Sat07 = 30, Sun08 = 22,
Mon09 = 20, Tue10 = 16, Wed11 = 24, Thu12 = 28, Fri13 = 31, Sat14 = 29, Sun15 = 17
)which(temps >= 20 & temps <= 25)Tue03 Thu05 Sun08 Mon09 Wed11
2 4 7 8 10
which(temps < 18 | temps > 28)Sat07 Tue10 Fri13 Sat14 Sun15
6 9 12 13 14
[]
Subsetting can be done using one of the following indexing methods:
Numeric indexing
Logical indexing
Character indexing (if the vector has names; not covered here)
# 1 2 3 4 5 6 7
v <- c(70, 66, 82, 85, 78, 90, 73)
# 1st value
v[1]
# 4th value
v[4]
# last value, 7th value
v[length(v)]
# Not available
v[320] # at 2nd, 3rd, 4th, 5th
v[2:5]
# at 5th, 4th, 3rd, 2nd
v[5:2]
# at 3rd, 1st, 3rd, 5th, 2nd
v[c(3, 1, 3, 5, 2)] # all but 1st value
v[-1]
# all but 2nd and 5th values
v[-c(2, 5)]
# all but 1st to 4th values
v[-(1:4)]
# error!
v[-1:4] 💻 Hands-On
Consider the following vector
# 1 2 3 4 5 6 7
v <- c(70, 66, 82, 85, 78, 90, 73)Write R code to return the following in v
The second value
The sixth value
The first and last values.
The values at positions 3 through 6
The values at positions 6 through 3
The values at positions 1, 4, and 7
All values except the first.
All values except the last two.
All values except positions 2 and 6.
v[2][1] 66
v[6][1] 90
v[c(1, length(v))][1] 70 73
v[3:6][1] 82 85 78 90
v[6:3][1] 90 78 85 82
v[c(1, 4, 7)][1] 70 85 73
v[-1][1] 66 82 85 78 90 73
v[-(6:7)] # or v[-c(6, 7)][1] 70 66 82 85 78
v[-c(2, 6)][1] 70 82 85 78 73
Logical indexing means telling R which values to return and which values not to return.
With logical indexing, TRUE will retain the elements, while FALSE will discard the elements.
Logical indexing is powerful because it allows for subsetting with conditions.
Consider the following vector
# 1 2 3 4 5 6 7
v <- c(70, 66, 82, 85, 78, 90, 73)
# 1st, 6th
v[c(TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE)]
# 2nd, 3rd, 4th
v[c(FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE)]
# those values greater than 80
v[v > 80] 💻 Hands-On
Consider the following vector
# 1 2 3 4 5 6 7
v <- c(70, 66, 82, 85, 78, 90, 73)Use numeric and logical indexing to subset
66 82 90 73
70 66 78 73
# 66 82 90 73
v[c(2, 3, 6, 7)]
v[c(FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE)]
# 70 66 78 73
v[c(1, 2, 5, 7)]
v[c(TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE)]
v[v < 80]💻 Hands-On
The monthly cost for a stand-alone drug plan varies from plan to plan and from state to state. The vector cost gives the premium for the plan with the lowest cost for each state in 2005 (excludes District of Columbia). Write R code using cost and state.name to find state(s) with a monthly premium
Less than or equal to \(\$5\)
Greater than \(\$10\)
Between \(\$5\) and \(\$10\) (exclusive)
Exactly equal to \(\$1.87\)
At most \(\$7\)
At least \(\$15\)
To be the smallest
To be the largest
# Recall the vector `state.name`
cost <- c(
14.08, 20.05, 6.14, 10.31, 5.41, 8.62, 7.32,
6.44, 10.35, 17.91, 17.18, 6.33, 13.32, 12.30, 1.87,
9.48, 12.30, 17.06, 19.60, 6.44, 7.32, 13.75, 1.87,
11.60, 10.29, 1.87, 1.87, 6.42, 19.60, 4.43, 10.65,
4.10, 13.27, 1.87, 14.43, 10.07, 6.93, 10.14, 7.32,
16.57, 1.87, 14.08, 10.31, 6.33, 7.32, 8.81, 6.93,
10.14, 11.42, 1.87
)state.name[cost <= 5][1] "Iowa" "Minnesota" "Montana" "Nebraska" "New Jersey"
[6] "New York" "North Dakota" "South Dakota" "Wyoming"
state.name[cost > 10] [1] "Alabama" "Alaska" "Arkansas" "Florida"
[5] "Georgia" "Hawaii" "Illinois" "Indiana"
[9] "Kentucky" "Louisiana" "Maine" "Michigan"
[13] "Mississippi" "Missouri" "New Hampshire" "New Mexico"
[17] "North Carolina" "Ohio" "Oklahoma" "Pennsylvania"
[21] "South Carolina" "Tennessee" "Texas" "West Virginia"
[25] "Wisconsin"
state.name[cost > 5 & cost < 10] [1] "Arizona" "California" "Colorado" "Connecticut"
[5] "Delaware" "Idaho" "Kansas" "Maryland"
[9] "Massachusetts" "Nevada" "Oregon" "Rhode Island"
[13] "Utah" "Vermont" "Virginia" "Washington"
state.name[cost == 1.87][1] "Iowa" "Minnesota" "Montana" "Nebraska" "North Dakota"
[6] "South Dakota" "Wyoming"
state.name[cost <= 7] [1] "Arizona" "California" "Delaware" "Idaho" "Iowa"
[6] "Maryland" "Minnesota" "Montana" "Nebraska" "Nevada"
[11] "New Jersey" "New York" "North Dakota" "Oregon" "South Dakota"
[16] "Utah" "Washington" "Wyoming"
state.name[cost >= 15][1] "Alaska" "Georgia" "Hawaii" "Louisiana"
[5] "Maine" "New Hampshire" "South Carolina"
state.name[cost == min(cost)][1] "Iowa" "Minnesota" "Montana" "Nebraska" "North Dakota"
[6] "South Dakota" "Wyoming"
state.name[cost == max(cost)][1] "Alaska"
Given a vector,
head() returns its first few elements
tail() returns its last few elements
sort() returns its sorted version in increasing or decreasing order
order() returns the indices of its sorted version
rev() returns the reversed vector
unique() returns a vector of its unique elements
table() shows unique elements and their frequencies
💻 Hands-On
The monthly cost for a stand-alone drug plan varies from plan to plan and from state to state. The vector cost gives the premium for the plan with the lowest cost for each state in 2005 (excludes District of Columbia).
cost <- c(
14.08, 20.05, 6.14, 10.31, 5.41, 8.62, 7.32,
6.44, 10.35, 17.91, 17.18, 6.33, 13.32, 12.30, 1.87,
9.48, 12.30, 17.06, 19.60, 6.44, 7.32, 13.75, 1.87,
11.60, 10.29, 1.87, 1.87, 6.42, 19.60, 4.43, 10.65,
4.10, 13.27, 1.87, 14.43, 10.07, 6.93, 10.14, 7.32,
16.57, 1.87, 14.08, 10.31, 6.33, 7.32, 8.81, 6.93,
10.14, 11.42, 1.87
)Try the following R code and see what it returns.
head(cost) # head(cost, n = 6)
tail(cost) # tail(cost, n = 6)
sort(cost)
sort(cost, decreasing = TRUE)
order(cost)
order(cost, decreasing = TRUE)
rev(cost)head(cost) # head(cost, n = 6)[1] 14.08 20.05 6.14 10.31 5.41 8.62
tail(cost) # tail(cost, n = 6)[1] 7.32 8.81 6.93 10.14 11.42 1.87
sort(cost) [1] 1.87 1.87 1.87 1.87 1.87 1.87 1.87 4.10 4.43 5.41 6.14 6.33
[13] 6.33 6.42 6.44 6.44 6.93 6.93 7.32 7.32 7.32 7.32 8.62 8.81
[25] 9.48 10.07 10.14 10.14 10.29 10.31 10.31 10.35 10.65 11.42 11.60 12.30
[37] 12.30 13.27 13.32 13.75 14.08 14.08 14.43 16.57 17.06 17.18 17.91 19.60
[49] 19.60 20.05
sort(cost, decreasing = TRUE) [1] 20.05 19.60 19.60 17.91 17.18 17.06 16.57 14.43 14.08 14.08 13.75 13.32
[13] 13.27 12.30 12.30 11.60 11.42 10.65 10.35 10.31 10.31 10.29 10.14 10.14
[25] 10.07 9.48 8.81 8.62 7.32 7.32 7.32 7.32 6.93 6.93 6.44 6.44
[37] 6.42 6.33 6.33 6.14 5.41 4.43 4.10 1.87 1.87 1.87 1.87 1.87
[49] 1.87 1.87
order(cost) [1] 15 23 26 27 34 41 50 32 30 5 3 12 44 28 8 20 37 47 7 21 39 45 6 46 16
[26] 36 38 48 25 4 43 9 31 49 24 14 17 33 13 22 1 42 35 40 18 11 10 19 29 2
order(cost, decreasing = TRUE) [1] 2 19 29 10 11 18 40 35 1 42 22 13 33 14 17 24 49 31 9 4 43 25 38 48 36
[26] 16 46 6 7 21 39 45 37 47 8 20 28 12 44 3 5 30 32 15 23 26 27 34 41 50
rev(cost) [1] 1.87 11.42 10.14 6.93 8.81 7.32 6.33 10.31 14.08 1.87 16.57 7.32
[13] 10.14 6.93 10.07 14.43 1.87 13.27 4.10 10.65 4.43 19.60 6.42 1.87
[25] 1.87 10.29 11.60 1.87 13.75 7.32 6.44 19.60 17.06 12.30 9.48 1.87
[37] 12.30 13.32 6.33 17.18 17.91 10.35 6.44 7.32 8.62 5.41 10.31 6.14
[49] 20.05 14.08
💻 Hands-On
The vectors scores and grades contain exam scores and the corresponding letter grades for students in a statistics class.
scores <- c(
88, 92, 75, 84, 91, 67, 73, 88, 95, 78,
82, 90, 69, 74, 85, 88, 93, 77, 81, 89,
94, 72, 68, 86, 80, 76, 83, 88, 91, 79
)
grades <- c(
'B', 'A', 'C', 'B', 'A', 'D', 'C', 'B', 'A', 'C',
'B', 'A', 'D', 'C', 'B', 'B', 'A', 'C', 'B', 'B',
'A', 'C', 'D', 'B', 'B', 'C', 'B', 'B', 'A', 'C'
)Write R code to:
Show the first and last few exam scores
Sort the exam scores in decreasing order
Show unique letter grades of students in this class and their frequencies
head(scores)[1] 88 92 75 84 91 67
tail(scores)[1] 80 76 83 88 91 79
sort(scores, decreasing = TRUE) [1] 95 94 93 92 91 91 90 89 88 88 88 88 86 85 84 83 82 81 80 79 78 77 76 75 74
[26] 73 72 69 68 67
table(grades)grades
A B C D
7 12 8 3