ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 06.04.2021

Просмотров: 880

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

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


background image

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


background image

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

20

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


background image

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


background image

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