I am not sure I understand the behaviour of the minus sign.
x <- 10:1
y <- c(4, 7)
x[y]
# [1] 7 4
x[-y]
# [1] 10 9 8 6 5 3 2 1
So the -
sign in x[-y]
is understood as items of x
that are not y
.
x <- 10:1
y <- 1:10
x[-y]
# integer(0)
Again logical, if y
has all the element of x
, x[-y]
should be empty.
Now if y
is itself empty, you'd expect that x[-y]
should list all the elements of x
.
However:
x <- 10:1
y <- integer()
x[-y]
# integer(0)
What is it that I am not understanding?
Is there any other operator to do what I want (i.e. list the elements of x
that are not in y
, and thus list all elements of x
is y
is empty)?
CodePudding user response:
@jay.sf's answer explains how to get what you want. I just wanted to add a bit more explanation, and give a suggestion for a different approach.
When you say x[-y]
, the minus sign doesn't have any special meaning: it just changes the sign of the elements of y
. It will give the same result as
z <- -y
x[z]
When y
is empty, z
will be empty as well, so x[y]
is the same as x[-y]
.
My recommendation is to use logical indices when you want to do logical operations on them. So you might have been doing this:
y <- which(x %% 50 == 11)
to choose the entries which meet the condition x %% 50 == 11
. Then if you
happen to have a vector where nothing meets the condition, you get an empty y
. A better approach is
y <- x %% 50 == 11
so that y
is a vector of all FALSE
values. If you want the complement, use
x[!y]
and you'll get all of x
.
CodePudding user response:
So the - sign in x[-y] is understood as items of x that are not y.
No, y
is used as indices of x
here. You can think of it like this:
setNames(x, paste0('x', seq_along(x)))
# x1 x2 x3 x4 x5 x6 x7 x8 x9 x10
# 10 9 8 7 6 5 4 3 2 1
x[-c(4, 7)] ## delete x4 and x7
# [1] 10 9 8 6 5 3 2 1
If you want elements in x
that are not in y
you need to say:
x[!x %in% y]
# [1] 10 9 8 6 5 3 2 1
y1 <- NULL
x[!x %in% y1]
# [1] 10 9 8 7 6 5 4 3 2 1
Or:
setdiff(x, y)
# [1] 10 9 8 6 5 3 2 1
setdiff(x, y1)
# [1] 10 9 8 7 6 5 4 3 2 1
Accordingly, in this one we delete all element indices from 1:10
, and since we have only 10 elements in x
we get the empty vector:
x[-(1:10)]
# numeric(0)
For the last one, we may read in documetation help("Extract")
, that "an empty index selects all values: this is most often used to replace all the entries but keep the attributes."
x[-integer()]
# integer(0)
How to delete nothing
If we want to delete nothing, we need an index that is higher than the number of elements in x
,
x[-11]
# [1] 10 9 8 7 6 5 4 3 2 1
where we could do dynamically:
x[-.Machine$integer.max]
# [1] 10 9 8 7 6 5 4 3 2 1