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

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

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

Добавлен: 06.04.2021

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

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

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

8.2. CHIMERAS

CIRCLE 8. BELIEVING IT DOES AS INTENDED

8.2.16

missing value in if

if(NA)

{

# creates error

It is a rather common error for an

if

condition to be

NA

. When this occurs, it

is common for the problem to be non-obvious. Debugging is called for in that
case.

8.2.17

and and andand

An alternative title here could have been ’or or oror’.

There are two ’and’ operators and two ’or’ operators:

8

&&

8

and

8

||

8

go with

if

8

&

8

and

8

|

8

go with

ifelse

8

&&

8

and

8

||

8

, like

if

, expect single element inputs. Because they only deal

with single elements, they can do shortcuts. If the answer is known with the
first (left) argument, then there is no need to evaluate the second.

>

if(TRUE || stop()) 4 else 5

[1] 4
>

if(TRUE && stop()) 4 else 5

Error:
>

if(FALSE || stop()) 4 else 5

Error:
>

if(FALSE && stop()) 4 else 5

[1] 5

This can be used to make sure that it is safe to perform a test, as in:

>

if(ncol(x) > 6)

{

...

Error in if (ncol(x) > 6) : argument is of length zero
>

if(is.matrix(x) && ncol(x) > 6)

{

... # okay

Note that in the last line

x

is excluded from being a data frame. If you want to

allow both data frames and matrices, then testing the length of

dim(x)

would

be an approach.

8.2.18

equal and equalequal

Just because

8

&&

8

and

8

&

8

have similar purposes, don’t go thinking that

8

==

8

and

8

=

8

are similar. Completely different.

Fortunately R keeps you from making this error in a key context:

>

if(x = 7)

{

...

Error: unexpected ’=’ in "if(x ="
>

if(x == 7)

{

... # okay

The difference is:

8

==

8

is a logical operator that tests equality.

8

=

8

is an assignment operator similar to

8

<

-

8

(but see Circle

8.2.26

).

90


background image

8.2. CHIMERAS

CIRCLE 8. BELIEVING IT DOES AS INTENDED

8.2.19

is.integer

is.integer

is a test of how the data are stored, it does not test if the numbers

are logically integers:

>

is.integer(c(4, 0, 3))

[1] FALSE

The key thing to say here is that, almost surely, you do not care if an object is
stored as integer. It is important if you are sending the data to C or Fortran.
Otherwise you can bask in the ease of letting R take care of details so you can
think about the big picture.

If you really want integers (that is, stored in integer format), then use “L”:

>

is.integer(c(4L, 0L, 3L))

[1] TRUE
>

is.integer(c(4L, 0L, 3))

[1] FALSE

The

8

:

8

operator is one of the few places in R where integers are produced :

>

is.integer(1:3)

[1] TRUE
>

is.integer(c(1:3, 4))

[1] FALSE
>

is.integer(c(1:3, 4:4))

[1] TRUE

Given experience with other languages, you may expect:

>

is.integer( 4. )

[1] FALSE
>

is.integer( 4 )

[1] FALSE

the first comand above to be

FALSE

and the second to be

TRUE

. That is, that

using a decimal point signifies that you want a floating point number as opposed
to an integer. As you see R has a fondness for floating point numbers.

You can coerce to integer, but (as always) be careful what you ask for:

>

as.integer(c(0, 1, -2.99, 2.99))

[1]

0

1 -2

2

8.2.20

is.numeric, as.numeric with integers

An integer vector tests

TRUE

with

is.numeric

. However,

as.numeric

changes

it from storage mode integer to storage mode double. If you care about it being
integer, then you want to use

as.integer

.

91


background image

8.2. CHIMERAS

CIRCLE 8. BELIEVING IT DOES AS INTENDED

>

is.integer(c(4L, 0L))

[1] TRUE
>

is.numeric(c(4L, 0L))

[1] TRUE
>

is.integer(as.numeric(c(4L, 0L)))

[1] FALSE

8.2.21

is.matrix

The

is.matrix

function can cause surprises, not least because it can give dif-

ferent answers in R and S+.

>

is.matrix(1:3)

[1] FALSE
>

is.matrix(array(1:3, c(3,1)))

[1] TRUE
>

is.matrix(array(1:3, c(3,1,1)))

[1] FALSE
>

is.matrix(array(1:3, 3))

[1] FALSE
>

is.matrix(data.frame(1:3))

[1] FALSE

# would be TRUE in S+

>

is.matrix(t(1:3))

[1] TRUE

The definition of “matrix” that

is.matrix

uses is that it is an array with a

dim

attribute of length 2. Note that the

t

function coerces a non-array to be a

(column) matrix and then does the transpose.

Some people want objects to be matrices by default. It isn’t going to happen.

R is a language of general objects, not a matrix language.

8.2.22

max versus pmax

I care not to try to count the number of times I’ve got this wrong, nor to tally
the hours I’ve spent tracking down the problem. And I’m only thinking of the
time after I knew very well the difference between

max

and

pmax

(and

min

and

pmin

).

Recall from Circle 3 (page

17

that there are two senses of vectorization.

max

and

pmax

are each vectorized but in opposite senses.

max

returns the single number that is the largest of all the input.

pmax

returns a vector that for each index location is the maximum across

inputs.

>

max(1:5, 6:2)

[1] 6

92


background image

8.2. CHIMERAS

CIRCLE 8. BELIEVING IT DOES AS INTENDED

>

pmax(1:5, 6:2)

[1] 6 5 4 4 5

The ’p’ in

pmax

stands for ’parallel’.

8.2.23

all.equal returns a surprising value

We met

all.equal

in Circle 1 (page

9

as an alternative to

8

==

8

. Numerical

error causes

8

==

8

not to provide a useful result in many cases.

if(all(x == y))

{

# wrong if there is numerical error

if(all.equal(x, y))

{

# WRONG, not FALSE when not equal

if(isTRUE(all.equal(x, y))

{

# right

8.2.24

all.equal is not identical

The purpose of

all.equal

is to compare items that may have some fuzziness

to them. Sometimes the fuzziness that

all.equal

sees can be surprising:

>

all.equal(as.numeric(NA), 0/0)

[1] TRUE

The

identical

function allows for no fuzziness at all:

>

identical(as.numeric(NA), 0/0)

[1] FALSE

8.2.25

identical really really means identical

>

xi <- 1:10

>

yi <- 1:10

>

identical(xi, yi[1:10])

[1] TRUE
>

yi[11] <- 11

>

identical(xi, yi[1:10])

[1] FALSE
>

zi <- 1:10

>

zi[11] <- 11L

>

identical(xi, zi[1:10])

[1] TRUE

xi

is stored as type integer. But once

yi

has been given one double value, it is

stored as double.

As has already been stated, you are unlikely to need to care about how

numbers are stored. If you think you care without a specific instance of why it
matters, you should probably get over it.

Though identical is very strict about what objects that it considers to be the

same, it doesn’t go as far as insisting that they share the same place in memory.
That is basically a foreign concept to R.

93


background image

8.2. CHIMERAS

CIRCLE 8. BELIEVING IT DOES AS INTENDED

8.2.26

= is not a synonym of

<

-

The

8

=

8

operator can mean the same thing as

8

<-

8

in a lot of circumstances,

but there are times when it is different.

Consider the command:

foo(93, a = 47)

versus

foo(93, a <- 47)

These two commands may lead to entirely different results. You clearly do not
want to use

8

<-

8

when you want to set an argument of a function.

A common occurrence where you don’t want to use

8

=

8

where

8

<-

8

is meant

is:

system.time(result <- my.test.function(100))

If you used

8

=

8

in the command above, R would think you were trying to set the

result

argument of

system.time

, which doesn’t exist. (If using

system.time

is not a common occurrence for you, perhaps it should be.)

Standard advice is to avoid using

8

=

8

when you mean

8

<-

8

even though it

takes an extra keystroke. However, it is largely a matter of taste (as long as you
know the differences).

8.2.27

complex arithmetic

The precedence with complex numbers may well not be what you expect. Con-
sider the command:

>

1+3i - 3+5i

[1] -2+8i

8.2.28

complex is not numeric

>

is.numeric(1+3i)

[1] FALSE

Complex numbers are numbers, but they are not numeric in R’s sense. To test
for numbers in the broader sense, you need:

is.numeric(x) || is.complex(x)

94