1

I just ran into an interesting nuance with the not ! operator in subsetting while answering this question link.

Check out:

y <- 1:10
y[!y]
integer(0)
y[4] <- NA
y[!y]
[1] NA
y[6] <- 0
y[!y]
[1] NA  0

From R documentation:

! indicates logical negation (NOT)

How is 0 and NA both NOT y?

Community
  • 1
  • 1
Pierre L
  • 28,203
  • 6
  • 47
  • 69
  • 1
    Anything operating on `NA` is `NA`, I think. I suspect this is a dupe. Here's my variant of it for data.table if you're interested: http://stackoverflow.com/questions/16221742/subsetting-a-data-table-using-some-non-na-excludes-na-too – Frank May 19 '15 at 16:07
  • Here's the nicest Q&A on it, I think. Not sure if you regard it as a dupe: http://stackoverflow.com/q/1773366/1191259 – Frank May 19 '15 at 16:16
  • no... check *this* out `length(NA); length(TRUE); y[NA]; y[TRUE]` – rawr May 19 '15 at 16:20

2 Answers2

1

You're not subsetting using equality, you are coercing the numerics 1:10 to logical--and any numeric other than 0 is coerced to TRUE. Run, e.g.,

!(1:10)
#  [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

You get 10 FALSEs, so when you subset a any vector of length 10 with 10 FALSEs, you get nothing.

As documented in ?TRUE and ?NA, a logical comparison with NA results in NA.

And, of course, 0 is coerced to FALSE, so !0 is coerced to TRUE, so when you set the 6th element to 0,

 !c(1:5, 0, 7:10)
 # [1] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE
 #         1     2     3     4     5  ^^^6     7     8     9    10

You get a TRUE in the 6th position, so subsetting with that will return the 6th element.

How is 0 and NA both NOT y?

You might be looking for y[y != y]?

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
  • Oh, right. Maybe the OP meant `-y` instead of `!y`. – Frank May 19 '15 at 16:10
  • 1
    @Frank Maybe. I think the OP meant `y[y != y]`, otherwise half the confusion is due to using `y` as both the vector and the indices to subset, whether with `-y` or `!y`. – Gregor Thomas May 19 '15 at 16:11
  • @Frank I meant to subset it the way I did. akrun used the logical replacement that Gregor mentioned in the question I linked to. It's clever. Just wanted to understand the logic. – Pierre L May 19 '15 at 17:01
  • @plafort Oh, I'd missed the link above because I'm terrible at reading; thanks for clarifying :) Personally, I'd linkify "this question" instead of appending "link" or "clicky here" to make it stand out more. By the way, **a possibly very important distinction**: your question is in fact not about the same thing as @akrun 's comment. You are asking about the subsetter `\`[\``, while he was using the assigner `\`[<-\`` – Frank May 19 '15 at 17:07
  • @Frank when he did `my_matrix[!my_matrix]` it interested me. But here's a thought, `as.logical(c(0,1,2,NA))` results in `[1] FALSE TRUE TRUE NA`. See `2` becomes `TRUE`. I thought `1` is `TRUE` and everything else is `FALSE` with binaries. It must be the opposite. – Pierre L May 19 '15 at 17:14
  • 2
    @plafort Yeah, to quote Gregor: "any numeric other than 0 [and NA] is coerced to TRUE" – Frank May 19 '15 at 17:16
0

0s are interpreted as FALSE in logical operations (Boolean algebra). !0 = !(FALSE) = TRUE.

Likewise, non-0 valid (i.e. non-NA) numerical values are interpreted as TRUE in logical operations.

The NAs are always tricky, see Frank's comment above.

W7GVR
  • 1,990
  • 1
  • 18
  • 24
  • Regarding the second line: `is.numeric(NA_integer_); !(NA_integer_)` is a counterexample. – Frank May 19 '15 at 16:28