ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 06.04.2021
Просмотров: 896
Скачиваний: 1
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
90
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
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
) 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
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
) 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
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