ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 06.04.2021
Просмотров: 905
Скачиваний: 1
8.1. GHOSTS
CIRCLE 8. BELIEVING IT DOES AS INTENDED
is evaluated as
(x1 == 4) | 6
(otherwise the two statements would get the same answer). This last statement
is the same as:
6 | (x1 == 4)
since “or” is commutative. The
8
|
8
operator coerces its arguments to be logical.
Any non-zero number coerces to
TRUE
, and so all elements of the resulting
command will be
TRUE
since 6 is coerced to
TRUE
.
The other statement has a different result but follows a somewhat similar
cascade of coercions.
4 | 6
is the same as
TRUE | TRUE
which is
TRUE
. So then R is being asked:
x1 == TRUE
The
8
==
8
operator coerces not to logical, but to the most general type, numeric
in this case.
TRUE
coerced to numeric is 1.
8.1.8
coercion
Automatic coercion is a good thing. However, it can create surprises. There is
an ordering of the modes for coercion—most specific to least specific—as shown
below.
>
modes <- c(’logical’, ’numeric’, ’complex’, ’character’)
>
modarr <- array(vector(’list’,16), c(4,4), list(modes,modes))
>
for(i in 1:4) for(j in 1:4)
{
+
modarr[[i, j]] <- c(vector(modes[i], 0),
+
vector(modes[j], 0))
+
}
>
modarr
logical
numeric
complex
character
logical
Logical,0
Numeric,0
Complex,0
Character,0
numeric
Numeric,0
Numeric,0
Complex,0
Character,0
complex
Complex,0
Complex,0
Complex,0
Character,0
character Character,0 Character,0 Character,0 Character,0
50
8.1. GHOSTS
CIRCLE 8. BELIEVING IT DOES AS INTENDED
This example leaves out the integer subtype of numeric. Integers go between
logical and (general) numeric. You are highly unlikely to need to care (or even
know) if an object is stored as integer or the more general numeric.
Here is the full list of atomic (storage) modes from most specific to most
general:
•
logical
•
integer
•
numeric
•
complex
•
character
Comment: This example uses a matrix that is a list. Notice the use of
8
[[
8
for the matrix. Some people arrive at such a matrix by accident—an event that
may lead to confusion.
8.1.9
comparison under coercion
Be careful when doing comparisons where coercion might come into play:
>
50 < ’7’
[1] TRUE
8.1.10
parentheses in the right places
You want to put parentheses in the right places so that it is the desired opera-
tions that are done:
>
length(mylist != 1)
Error: (list) object cannot be coerced to double
>
length(mylist) != 1
[1] TRUE
In this example we are lucky enough to get an error so we know something is
wrong.
8.1.11
excluding named items
Negative subscripts allow you to say which items you don’t want:
>
xlet <- 1:6
>
names(xlet) <- letters[1:6]
>
xlet[-c(3,4)]
a b e f
1 2 5 6
51
8.1. GHOSTS
CIRCLE 8. BELIEVING IT DOES AS INTENDED
Sometimes you would like to do the excluding with names rather than numbers,
but this does not work (naturally enough):
>
xlet[-c(’c’, ’d’)]
Error in -c("c", "d") : Invalid argument to unary operator
There is a reasonable way to get the behavior though:
>
xlet[!(names(xlet) %in% c(’c’, ’d’))]
a b e f
1 2 5 6
Actually parentheses are not needed:
>
xlet[!names(xlet) %in% c(’c’, ’d’)]
a b e f
1 2 5 6
But it seems like magic to me that this works—I feel more comfortable with the
parentheses. Uwe’s Maxim (page
) comes into this for me: I need to think
less when the parentheses are there.
The negative of a character string does work in some circumstances in
subset
, but note that there are warnings coming up about using
subset
.
8.1.12
excluding missing values
>
xna <- c(1, NA, 3, 2, 4, 2)
>
xna[xna == 2]
[1] NA 2 2
As you can see, if you only wanted the values that are for sure 2, then you would
be disappointed. If that is what you want, then you need to say so:
>
xna[!is.na(xna) & xna == 2]
[1] 2 2
Or more compactly:
>
xna[which(xna == 2)]
[1] 2 2
8.1.13
negative nothing is something
>
x2 <- 1:4
>
x2[-which(x2 == 3)]
[1] 1 2 4
The command above returns all of the values in
x2
not equal to 3.
52
8.1. GHOSTS
CIRCLE 8. BELIEVING IT DOES AS INTENDED
>
x2[-which(x2 == 5)]
numeric(0)
The hope is that the above command returns all of
x2
since no elements are
equal to 5. Reality will dash that hope. Instead it returns a vector of length
zero.
There is a subtle difference between the two following statements:
x[]
x[numeric(0)]
Subtle difference in the input, but no subtlety in the difference in the output.
There are at least three possible solutions for the original problem.
out <- which(x2 == 5)
if(length(out)) x2[-out] else x2
Another solution is to use logical subscripts:
x2[!(x2 %in% 5)]
Or you can, in a sense, work backwards:
x2[ setdiff(seq along(x2), which(x2 == 5)) ]
8.1.14
but zero can be nothing
>
x3 <- 1:3
>
x3[c(0, 4)] <- c(-1, 9)
Warning message: number of items to replace is not
a multiple of replacement length
>
x3
[1] 1 2 3 -1
This is an instance where you don’t want to ignore the warning message because
the fourth element does not get its intended value.
8.1.15
something plus nothing is nothing
>
1 + NULL
numeric(0)
This computation goes through without error or warning. It works because the
recycling rule says that the length of the result should be 0. Sometimes you
would prefer to be warned.
53
8.1. GHOSTS
CIRCLE 8. BELIEVING IT DOES AS INTENDED
8.1.16
sum of nothing is zero
Some people are surprised by:
>
sum(numeric(0))
[1] 0
And perhaps even more by:
>
prod(numeric(0))
[1] 1
The counterparts in logicland are:
>
any(logical(0))
[1] FALSE
>
all(logical(0))
[1] TRUE
Surprising or not, these are the correct answers. We demand that
sum(c(1, 3, 5, 7))
equals
sum(c(1, 3)) + sum(c(5, 7))
So we should also demand that it equals:
sum(c(1, 3, 5, 7)) + sum(numeric(0))
Similar behavior occurs with min and max, although there are warnings with
these:
>
min(NULL)
[1] Inf
Warning message:
In min(NULL) : no finite arguments to min; returning Inf
>
max(NULL)
[1] -Inf
Warning message:
In max(NULL) : no finite arguments to max; returning -Inf
8.1.17
the methods shuffle
While a matrix and a data frame can represent the same data and may look
the same, they are different. In particular, generic functions can and do give
different results.
Let’s start by making some data:
54