Reputation: 72909
From a matrix M
,
> (M <- matrix(1:9, 3, 3))
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
I want to remove/keep columns by condition and put the result into a list. There's no problem as long as the condition consists of integers without c(NA, 0)
, e.g.
cv1 <- 1:3
lapply(cv1, function(x) M[, -x])
For the case there's no column to remove I tried to add NA
or 0
to the condition vector, but it won't work.
cv2 <- c(NA, 1:3)
cv3 <- 0:3
> lapply(cv2, function(x) M[, -x])[[1]]
[1] NA NA NA
> lapply(cv3, function(x) M[, -x])[[1]]
[1,]
[2,]
[3,]
I know I can do
lapply(cv2, function(x) {
if (is.na(x))
M
else
M[, -x]
})
but I wonder if there's a simpler way.
Actually question:
What strikes me in the first place is that the matrix disappears instead of remaining complete in following cases, although I'm actually trying to remove nothing:
M[, -(na.omit(NA))]
M[, na.omit(-(NA))]
M[, -0]
M[, -logical(0)]
# [1,]
# [2,]
# [3,]
or
> M[, -NULL]
Error in -NULL : invalid argument to unary operator
Can somebody explain the reason and the advantage of this behavior, and/or how to say it right?
Upvotes: 1
Views: 91
Reputation: 44877
The reason is pretty simple: the minus sign in -x
isn't treated as something special, it's just a regular mathematical operation. So -0
is the same as 0
, and -NA
is the same as NA
.
@Cettt gave one answer: setdiff(seq_len(ncol(M)), x)
will give the column numbers other than x
. You can do the same sort of thing using logical indexing as seq_len(ncol(M)) != x
will work if x
is a number, but not if x
is NA
. If you really need to handle that case too, you could use is.na(x) | seq_len(ncol(M)) != x
, but @Cettt's solution looks simpler.
Upvotes: 1