# Errata

## Errata for The Art of R Programming

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
Printed Page 6
last paragraph

pressing CTRL-D in Linux or CMD-D on a Mac
should be
pressing CTRL-D Linux or on a Mac

Yue Zhou  Mar 19, 2012
PDF Page 11
the 14th from the bottom

the author describes a portion of the code as follows : "Finally, we multiplied
the vector (5,4) by m. In order to get matrix multiplication of the mathematical type, we used the %*%
operator."

the portion of the code in questions is the following

> m %*% c(1,1)
[,1]
[1,] 5
[2,] 4

as we see, the multiplication is between m and a vector = (1,1) not a
vector = (5,4)

Mouad Seridi  Aug 09, 2015
Printed Page 23
5 lines from bottom

"NumericaConstants" should be "NumericConstants"

Alan Reynolds  Nov 14, 2012
PDF Page 30
Taiwan

page 30 is explaining the vector recycling.
one example depicted that a vector is added to matrix with 3x2 dimension.
the result of the addition should be
2 6
3 6
4 8

however, the result on page 30 is as follow
2 6
4 6
4 8

Guo-Guang Chiou  Apr 19, 2012
Printed Page 34
Top section

On page 27, it is stated that "for careful coding you should worry that length(x) might be zero". Now, on page 34, this problem is 'fixed' by writing "for (i in seq(x))". However, for careful coding one should also worry that length(x) might be one! For example, if vector x just contains the number 5, then seq(x) is 1,2,3,4,5 and the code will attempt to iterate over elements of the vector that are not there.

Alan Reynolds  Nov 14, 2012
Printed Page 34
United States

As already noted, the use of "seq" with a vector of length one causes problems. Please note that "seq_along" is intended to solve this. See http://stackoverflow.com/questions/13732062/seq-vs-seq-along-when-will-using-seq-cause-unintended-results

Michael Albert  Aug 24, 2014
PDF Page 34
1st paragraph of Section 2.4.5

The text says

The rep() (or repeat) function

I think the intended sentence was:

The rep() (for repeat) function

because repeat is an entirely different R function.

razorbill  Apr 01, 2016
PDF Page 34
1st paragraph of Section 2.4.5

I just wanted to share my opinion that the error reported by razorbill is not actually an error.

Where the book reads "rep (or repeat)", the italicized "repeat" just means that the name "rep" is short for repeat. It is not saying that "rep" is synonymous with the "repeat" function. If "repeat" were referring to a function, the monospace font for function names would be used.

The author's intent can be seen from page 42, where the same wording is used: "sapply (or simplify apply)". "simplify apply" is clearly not a function; it is just explaining for what "sapply" is an abbreviation.

Anonymous  Nov 05, 2019
Printed Page 36
Third section of code

The code where preallocation of the memory space takes place made sense - at least until I got to the note on page 74, which indicates that x[2] <- 12 is actually a reassignment. (See also page 314). So it would appear that reassignment (and hence reallocation) still occurs on line 8 of the code, and is not avoided after all!

I'm sure the new code is more efficient - however, I begin to suspect that the reason is more subtle than simply avoiding reassignment/reallocation.

Alan Reynolds  Jan 10, 2013
Printed Page 39
Second code chunk

# the vector red ...
# the vector pred ...

R. Mark Sharp  Jan 04, 2012
Printed Page 39
middle of page, in predc function example

In the comment "# the vector red will contain our predicted values"
"red" should be "pred"

Anonymous  Nov 17, 2015
Printed Page 41
4th example on page

the assignment operator "<-" is missing between "f" and "function(x,c) return((x+c^2)"

Anonymous  Nov 17, 2015
Other Digital Version 42
United States

"Let's first read in the data file:

Our file does not include a header line naming the variables in each student record, so we specified header=FALSE in the function call. This is an example of a default argument, which we talked about earlier."

Specifying the value of an argument by assigning it to the formal parameter (header=FALSE) in a function call is not "an example of a default argument". It's a keyword argument. Default arguments are specified like this in the function definition, not a call.

Sean Mackesey  Nov 27, 2012
Printed Page 44
Last sentence of 3rd paragraph

Here are two more ways another way to find ...
Here are two more ways to find ...

R. Mark Sharp  Jan 04, 2012
Printed Page 49
First line of comment in code at page bottom

findud() does not convert v to 1s and 0s - it converts to 1s and -1s.

Alan Reynolds  Nov 16, 2012
Printed Page 53
Last line of code and second to last paragraph

The second to last paragraph suggests that the second plot command superimposes the graph for females on the same graph as the males. This is not the case, and it is not merely because one set of data covers the other. Compare with the results obtained if the last line is replaced by "points(abaf$Length, abaf$Diameter,pch="x")".

Alan Reynolds  Nov 16, 2012
Printed Page 53

The line:
for (gen in c("M","F")) grps[[gen]] <- which(aba==gen)
won't work if the male column isn't first.
I think it's better to change it to:
for (gen in c("M","F")) grps[[gen]] <- which(aba$male==gen) Anonymous Jul 02, 2015 Printed Page 54 Second paragraph Of course, the compacted code will also plot an x for each infant abalone too. Alan Reynolds Nov 16, 2012 Printed Page 55 Fourth paragraph, middle of page Just because all(x == y) is true does not necessarily mean that the vectors are identical, due to recycling. Consider x <- c(1, 2) y <- c(1, 2, 1, 2) all(x == y) Alan Reynolds Nov 16, 2012 PDF Page 56 above par 6.2 "the element of the second row, first column, i.e. the Exam 2 score for the second student." should read "the element of the second row, first column, i.e. the Exam 1 score for the second student." Anonymous Jul 04, 2017 PDF, ePub Page 65 R code at the bottom At the bottom of page 65, the R codes may not work correctly. The function blurpart() tries to introduce random noises to a portion of the image. However, on the line newimg@grey <- (1-q) * img@grey + q * randomnoise the matrices may be of different dimensions. The matrix img@grey has a dimension of the original image, but the matrix randomnoise has a dimension of lrows by ncols. The matrix addition won't work. A modification of the code may be: randomnoise = img@grey randomnoise[round(rows[1]):round(rows[lrows]),round(cols[1]):round(cols[lcols])] = matrix(nrow=lrows, ncol=lcols, runif(lrows*lcols)) Gu Mi Oct 18, 2012 Printed Page 65 code block at bottom of page As someone else submitted, the code does not work. How did the author generate the image yet still not provide working code? I'm baffled. This code seems more straightforward than what alittleboy submitted. blurpart <- function(img,rows,cols,q){ lrows<- length(rows) lcols<- length(cols) newimg <- img randomnoise <- matrix(nrow=lrows, ncol=lcols,runif(lrows*lcols)) newimg@grey[rows,cols] <- (1-q) * img@grey[rows,cols] + q * randomnoise return (newimg) } pfaffman Jan 07, 2013 Printed Page 65 2nd code block Two errors in this code block. First off in the description of the randomnoise matrix, the variable "ncols" has been used which wasn't defined previously. It should read "lcols". Second even after this correction has been made. R throws an error about the array sizes not matching up: Error in (1 - q) * img@grey + q * randomnoise : non-conformable arrays This makes sense because randomnoise is defined as the smaller matrix that is fuzzy and covers the president's face, and nothing is done to place that matrix over the actual location of the president's face in the original larger matrix. > lrows<- length(84:163) > lcols <- length(135:177) > newimg <- mtrush1 > q <- 0.65 > randomnoise <- matrix(nrow=lrows, ncol=lcols, runif(lrows*lcols)) > dim(randomnoise) [1] 80 43 > dim(mtrush1@grey) [1] 194 259 > newimg@grey <- (1-q) * mtrush1@grey + q * randomnoise Error in (1 - q) * mtrush1@grey + q * randomnoise : non-conformable arrays Here is the code with the first error I pointed out fixed, not sure how to fix the second error: blurpart <- function(img,rows,cols,q){ lrows <- length(rows) lcols <- length(cols) newimg <- img randomnoise <- matrix(nrow=lrows, ncol=lcols, runif(lrows*lcols)) newimg@grey <- 1-q * img@grey + q * randomnoise return(newimg) } John St. John Nov 09, 2013 Printed Page 65 2nd code block The definition of blurpart should be blurpart <- function(img,rows,cols,q) { lrows <- length(rows) lcols <- length(cols) newimg <- img randomnoise <- matrix(nrow=lrows, ncol=lcols, runif(lrows*lcols)) newimg@grey[rows, cols] <- (1-q) * img@grey[rows, cols] + q * randomnoise return(newimg) } Anonymous Jul 02, 2015 Printed Page 67-67 last line of page 67 - start of page 68 The book says "Here's an example with the same x as above". The x used above is x = matrix(c(1,2,3,2,3,4),nrow=3). The results here should then be matrix(c(1,2,3,4),nrow=2). Anonymous Dec 26, 2011 Printed Page 67,68 end/start The results here should then be matrix(c(1,3,2,4),nrow=2). Anonymous Jan 23, 2012 Printed Page 67 Bottom While the x is "the same as above", what is z? Alan Reynolds Dec 06, 2012 Printed Page 67 Last paragraph The code at the bottom of page 67 does not work. If I type x[z %% 2 == 1,] with the correct matrix x set, R returns the error: "Error in x[z%%2 == 1, ] : (subscript) logical subscript too long." I can get the correct output when I type: x[x[,1] %% 2 == 1,] The author writes: "The filtering criterion can be based on a variable separate from the one to which the filtering will be applied." I can't make that work. R might have removed that feature from the latest version. Evan St. Claire Sep 07, 2015 Printed Page 69 1 paragraph of the new section The paragraph deals with the row and col functions. The text states (correctly) that their arguments are matrices. Then it suggests that, if a is a matrix, row(a[2,8]) will return the row number of that element of a, which is 2. However, my understanding (and R docs and interpreter seem to agree with me) is that the code above could not possibly work. > a <- matrix(1:32, nrow=4, ncol=8) > a [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [1,] 1 5 9 13 17 21 25 29 [2,] 2 6 10 14 18 22 26 30 [3,] 3 7 11 15 19 23 27 31 [4,] 4 8 12 16 20 24 28 32 > is.matrix(a) [1] TRUE Here we have created a matrix (and the system correctly recognizes it as a matrix). However, the suggested code does not work: > row(a[2,8]) Error in row(a[2, 8]) : a matrix-like object is required as argument to 'row/col' which is not surprisingly, considering that: > is.matrix(a[2,8]) [1] FALSE BTW, row(a) works (and does the expected thing). > row(a) [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [1,] 1 1 1 1 1 1 1 1 [2,] 2 2 2 2 2 2 2 2 [3,] 3 3 3 3 3 3 3 3 [4,] 4 4 4 4 4 4 4 4 The rest of the chapter proceeds using row and col properly and the usage suggested in the first paragraph is never ever attempted again. Enrico Franchi Nov 09, 2012 Printed Page 69 4th paragraph 'Correlation' should perhaps read 'covariance'. (Very minor!) Alan Reynolds Dec 06, 2012 Printed Page 72 Start of code chunk Missing a " -> " 3rd err' found Anonymous Jan 25, 2012 Printed Page 72 First line of code It looks like the assignment operator was left out of the function definition: copymaj function should be copymaj <- function Robert S Jan 14, 2013 Printed Page 74 In code, middle of page: results of cbind(one,z) The matrix resulting from cbind(one, z) should have a column header of "one" in the output, but it doesn't. Robert S Jan 14, 2013 Printed Page 75 Paragraph immediately before 2nd code chunk Be careful with rbind and cbin() ... has two errors and should read Be careful with rbind() and cbind() ... R. Mark Sharp Jan 04, 2012 Printed Page 75 First paragraph after first code example "Be careful with rbind and cbin(), though." should be: "Be careful with rbind() and cbind(), though." That's two errors -- one of missing parentheses and one of missing 'd'. Robert S Jan 14, 2013 Printed Page 76 First chunk of code # wmins will be 2x(n-1), instead of 2xn. Lin Zhang May 22, 2017 Printed Page 77 4th paragraph (i+1):(1x-1) should read (i+1):(lx-1) 4th err' Anonymous Jan 26, 2012 Printed Page 77 3rd paragraph "mininum" should read "minimum" (twice) Matthew Gillman Dec 29, 2015 Printed Page 82/83 Throughout 3rd row, 2nd col entries in both firsttest & secondtest "wrong" (well, changed as if by some perverse magic on next page), making much on page 83 nonsense. A minor error, if you know matrices. 2nd errata posting Anonymous Jan 25, 2012 Printed Page 93 Lines 10-11 The sentence states how convenient it is that list indexing can be done through quoted strings, when perhaps it should say bracketed strings - the code itself doesn't use quoted strings. (Very minor) Alan Reynolds Jan 15, 2013 Printed Page 98 2nd code chunk, 3rd line > snyt <- freqwl(nyt) should read > ssnyt <- freqwl(nyt) R. Mark Sharp Jan 04, 2012 Printed Page 98 New York Times example There is a statement missing after the line snyt <- freqwl(nyt): > ssnyt <- sapply(snyt, length) # calculate the frequency this makes sense, as in the two lines below ssnyt is referenced and barplot needs a vector or matrix as first parameter. Wolfgang Kittenberger Dec 16, 2012 PDF Page 100 2nh paragraph from the bottom of the page The paragraph treats the recursive argument to c() as if it determines the type of output of c() and thus leads to the conclusion "ItÃ¢â‚¬â„¢s odd that setting recursive to TRUE gives a nonrecursive list.)". However, the recursive argument determines if the concatenate function, i.e. c(), recursively travels through the the arguments of the list or not. Thus, if recursive=FALSE the concatenate function builds the vector usuiing only the first level names of the list. This is exactly how the unix family utilities work too and no doubt the pattern out of which c() was designed after. No need to introduce confusion! Umbromancer Jun 22, 2020 Printed Page 103 1st paragraph "would generally considered to" should read "would generally be considered to" Matthew Gillman Dec 29, 2015 Printed Page 109 1st code block grep("Programmer", all2006) returns the column numbers in which "Programmer" occurs, not the rows as intended to filter the row of the data frame. I believe it should be grep("Programmer", all2006$occupation) to search in the occupation column or
grep("Programmer", as.data.frame(t(all2006),stringsAsFactors=F))) to search in all columns.

Jacques Philip  Dec 28, 2011
PDF Page 111
code at the top

Code line
> d2a <- rbind(d2,list(15,"Jill"))
creates error because the objects in the list(15, "Jill") does not match with the objects in d2

The corrected code is
> d2a <- rbind(d2,list("Jill",15))

Printed, PDF Page 112

Section 5.4.1 does not provide an example of using sapply() on data frames. This might be relevant, because sapply applied to a data frame returns a matrix, not a data frame and this might lead to unwanted coercion.

Anonymous  Jan 28, 2018
Printed Page 114
R session output

The output from "loall" lists (Intercept) and clmn for the first 6 variables. However, for the last two "col" is used instead of "clmn". i.e. it's inconsistent.

Matthew Gillman  Dec 29, 2015
PDF Page 114
end of page

It is mentioned that
> class(loall)
[1] "glm" "lm"

while I get the answer
> class(loall)
[1] "matrix"

Printed Page 115
Last paragraph

"This a job made for R!"

"This is a job made for R!"

Matthew Gillman  Dec 29, 2015
Printed, PDF Page 116
Last sentence on page

The author states that "We know from the result of the preceding example that there are SIX such characters." However, the preceding example shows that there are FIFTEEN such characters.

Anonymous  Jan 28, 2018
PDF Page 118
Line 37 of code

Line 37 of the code reads:

numtones <- tone %in% letters # T is 1, F is 0

numtones <- !(tone %in% letters) # T is 1, F is 0

We want numtones to be 1 when there *is* a tone number at the end of the pronun variable.
However if the last character is a number, then it is *not* a letter and (tone %in% letters) returns FALSE = 0.
Therefore we need to flip the boolean state.

Anonymous  Apr 25, 2015
Printed, PDF Page 118
Line 19 of the code

The intention of line 19 of the code for the function merge2fy is to merge the data frames outdf and tmpdf through the merge function. The merge function creates a new data frame by looking for ALL possible matches between ALL columns of outdf and tmpdf, and therefore, a long list is produced.

However, the author's intention is to merge outdf and tmpdf based on the common first column holding the Chinese characters. Therefore, the code in line 19 should read:

outdf <- merge(outdf,tmpdf,by.x=1,by.y=1)

to ensure that the merge is only based on the common first column in both data frames.

PS: Although the canman8 data set is not available on the author's website anymore, this extended example can be tested if one makes data frames from the tables printed in the book on p. 116 and 117.

Anonymous  Jan 28, 2018
Printed, PDF Page 118
Code in line 38

Anonymous' remark on 25 April, 2015 is correct. However, if applied, the code in line 38 needs to be updated to:

if (numtones == 0) tone <- NA

to prevent that tone is set to NA when there IS a tone.

Anonymous  Jan 28, 2018
PDF Page 122
Line 10

attr(,"levels") should be read as attr(xf,"levels")

Printed Page 124
2nd paragraph (last before section 6.2.2)

"applied to mean() function"

"applied the mean() function"

Matthew Gillman  Dec 29, 2015
Printed Page 130
3rd paragraph of 6.3.1

printed: cttab had class "cttab",...
should be: cttab had class "table",...

Matthew Perry  Apr 21, 2014
Printed Page 130
6.3.1

class "cttab" should be class "table" and column should be row

In the second command, even though the first command had shown that cttab had class "cttab", we treated it as a matrix and printed out its "[1,1] element." Continuing this idea, the third command printed the first column of this "matrix."

The sentence SHOULD read:

In the second command, even though the first command had shown that cttab had class "table", we treated it as a matrix and printed out its "[1,1] element." Continuing this idea, the third command printed the first row of this "matrix."

Anonymous  Jul 27, 2015
PDF Page 130
last chunk of code

>ctt/5 should be
>cttab/5

PDF Page 130
4

There appears "that cttab had class Ã¢â‚¬Å“cttabÃ¢â‚¬Â" and I think should be "that cttab had class Ã¢â‚¬Å“tableÃ¢â‚¬Â". Even though, if I am right, this is a really minor point!

Reynaldo Senra  Sep 08, 2016
PDF Page 131
First chunk of code

apply(ctt,1,sum) should be

apply(cttab,1,sum)

Printed Page 132
1st paragraph

printed: respondents who know they will vote for X...
should be: respondents who know whether they will vote for X...

Matthew Perry  Apr 21, 2014
Printed Page 134
3rd paragraph, bullet "dim"

printed: this is the value ndims
should be: this is the value dims

Matthew Perry  Apr 21, 2014
PDF Page 137
second last paragraph

This says that z[1], 0.88114802, fell into bin 9, which was (0,0,0.1]; z[2],
0.28532689, fell into bin 3; and so on.

should be

This says that z[1], 0.88114802, fell into bin 9, which was (0,8,0.9]; z[2],
0.28532689, fell into bin 3; and so on.

Printed, PDF Page 147
Second oddcount() example

In the second example of the oddcount() code, the line with 'pagebreak' should be removed.

Anonymous  Feb 03, 2018
Printed Page 151
3rd code block

> g <- function(h,a,b) h(a,b)
> body(g) <- quote(2*x + 3)
> g
function (x)
2 * x + 3
> g(3)
[1] 9

but formals() has not been changed and x is neither in passed parameters nor in .GlobalEnv:

> g <- function(h,a,b) h(a,b)
> body(g) <- quote(2*x + 3)
> g
function (h, a, b)
2 * x + 3
> g(3)
Error in g(3) : object 'x' not found

Dirk Sarpe  Aug 05, 2012
Printed Page 154-155
Code samples

Multiple missing "<-"s.

5th error.

Anonymous  Feb 04, 2012
Printed Page 160
4th block of R code

> oddsevens
function (v){
odds <- which(v %% 2 == 1)
evens <_ which(v %% 2 ==1)
list(o=odds,e=evens)
}

should be

> oddsevens
function (v){
odds <- which(v %% 2 == 1)
evens <_ which(v %% 2 ==0) # changed 1 to 0 to get evens
list(o=odds,e=evens)
}

William Murrah  Mar 10, 2013
Printed Page 185
Line 25

Some LaTeX obvisoulsy got mixed with code, i.e., \begin{Code} and \end{Code} apearing in actual R code

Simon Knaus  Jun 13, 2012
PDF Page 195
2nd paragraph

I think that in the paragraph "What happened here? We called order() on the second column of y, yielding a vector r, telling us where numbers should go if we want to sort them. The 3 in this vector tells us that x[3,2] is the smallest number in x[,2]; the 1 tells us that x[1,2] is the second smallest; and the 2 tells us that x[2,2]
is the third smallest. We then use indexing to produce the frame sorted by column 2, storing it in z."

All the x should be y.

Reynaldo Senra  Sep 12, 2016
PDF Page 197
First line of matrix solving code.

Though the matrix code and its output are self-consistent, they don't match the matrix presented in the example.

The matrix 'a' that's supposed to be created is ((1,1),(-1,1)), but instead the matrix created by the R code is ((1,-1),(1,1)) because of the vector input (1,1,-1,1) is read in as columns to create the matrix. This can be fixed by adding byrow=T when creating the matrix:

a <- matrix(c(1,1,-1,1), nrow=2, ncol=2, byrow=T)

Rasmi  Jul 27, 2015
PDF Page 204
footnote

A sequence of independent 0- and 1- valued random variables with the same probability of 1 for each is called Bernoulli.

should be

A sequence of independent 0- and 1- valued random variables with the same probability of 0.5 for each is called Bernoulli.

or

A sequence of independent 0- and 1- valued random variables with the probability of p and q = 1-p is called Bernoulli.

Printed Page 212
3rd paragraph

It's claimed that "a class instance is created by forming a list...", but in R any object (data.frame, vector, matrix, whatever) can take a 'class' attribute and participate in method dispatch.

Ken Williams

Dec 28, 2011
Printed Page 264
Section 12.1.3

X11(), macintosh() and windows() functions are introduced stating that you can use them to print two graphs side by side.

On my system macOS Catalina R reports it can't find macintosh().
A fast search online yielded no results. So it is possible that it is my installation, but also a deprecated practice or even an error in the book. However, a sure way to achieve the effect that seems more universal is:

par(mfrow=c(1,2)) # c(n.rows, n.cols) in the output
hist(x)
hist(y)

Umbromancer  Jul 09, 2020