[R] Removing elements ..., NO bug in which() function

Henrik Bengtsson hb at biostat.ucsf.edu
Thu Feb 24 05:23:08 CET 2011


On Wed, Feb 23, 2011 at 1:02 PM, Martin Maechler
<maechler at stat.math.ethz.ch> wrote:
>>>>>> "RK" == Rumen Kostadinov <rkostadi at gmail.com>
>>>>>>     on Sun, 13 Feb 2011 12:46:52 -0500 writes:
>
>    RK> Thanks Sarah,
>    RK> Yes, the function behaves Exactly as documented:
>
>    RK> check this out:
>    >> a = c(1,2,3,4,5)
>    >> a[which(a!=6)]
>    RK> [1] 1 2 3 4 5
>    >> a[!which(a==6)]
>    RK> numeric(0)
>    >> a[-which(a==6)]
>    RK> numeric(0)
>    >> a[!a==6]
>    RK> [1] 1 2 3 4 5
>
>    RK> I guess this is just a "gotcha", since
>    RK> I often use !which and -which to remove elements,
>    RK> So one should use
>    RK> a[which(a!=stuff to remove)]
>    RK> instead of
>    RK> a[-which(a==stuff to remove)]
>    RK> a[!which(a==stuff to remove)]
>
> BTW: you have just seen why you should *NOT* use
>      a[ -which() ]
>
> and probably should use which() much less than you currently do.
> Some useRs seem overly fond of which() instead of working with
> the logical vectors directly ...
> {{Yes, I know that in some situations  which() "works with NAs"...}}
>
> I think we (R-core) should get back to Bill Dunlap's suggestions
> on the R-devel list and think of providing fast functions for
> things like   "L && !is.na(L)"
> ...
> in other words, versions of the utilities I have in (the R
> package) Matrix/R/Auxiliaries.R,
>
>  ## Need to consider NAs ;  "== 0" even works for logical & complex:
>  ## Note that "!x" is faster than "x == 0", but does not (yet!) work for complex
>  ## if we did these in C, would gain a factor 2 (or so):
>  is0  <- function(x) !is.na(x) & x == 0
>  isN0 <- function(x)  is.na(x) | x != 0
>  is1  <- function(x) !is.na(x) & x   # also == "isTRUE componentwise"
>
>  ##
>  all0 <- function(x) !any(is.na(x)) && all(!x) ## ~= allFalse
>  any0 <- function(x) isTRUE(any(x == 0))             ## ~= anyFalse
>  ## These work "identically" for  1 ('==' TRUE)  and 0 ('==' FALSE)
>  ##    (but give a warning for "double"  1 or 0)
>  ## TODO: C versions of these would be faster
>  allTrue  <- function(x) all(x)  && !any(is.na(x))
>  allFalse <- function(x) !any(x) && !any(is.na(x))## ~= all0
>  anyFalse <- function(x) isTRUE(any(!x))                ## ~= any0
>
>
> Note that I comment twice that it would be nice to have fast
> versions of these (via C).

Well, at least for any(is.na(x)) there is a fast ("early stopping")
implementation in anyMissing(x) of the 'matrixStats' package (also in
Biobase of Bioconductor).  As the author I say: feel free to include
it in "base" R.  Code is available at:

 https://r-forge.r-project.org/scm/viewvc.php/pkg/matrixStats/?root=matrixstats

See files R/anyMissing.R and src/anyMissing.c

At least a start.

/Henrik

>
> Martin
>
>
>
>    RK> On Sun, Feb 13, 2011 at 12:37 PM, Sarah Goslee
>    <sarah.goslee at gmail.com> wrote:
>    >> If by "bug" you mean "function behaving exactly as documented."
>    >>
>    >> which() returns only the matches, the TRUE values. If there are
>    >> no matches, it doesn't return anything.
>    >>
>    >> If I understand what you are trying to do, and I may not,
>    >> a[which(a != 5)] is really what you want, and it is precisely
>    >> to preserve that behavior that which() does what it does.
>    >>
>    >> Sarah
>    >>
>    >> ---
>    >>
>    >> which                   package:base                   R
>    >> Documentation
>    >>
>    >> Description:
>    >>
>    >>     Give the ‘TRUE’ indices of a logical object, allowing for
>    >> array     indices.
>    >>
>    >> Value:
>    >>
>    >>     If ‘arr.ind == FALSE’ (the default), an integer vector with
>    >>     ‘length’ equal to ‘sum(x)’, i.e., to the number of ‘TRUE’s
>    >> in ‘x’;     Basically, the result is ‘(1:length(x))[x]’.
>    >>
>    >> ---
>    >> On Sun, Feb 13, 2011 at 11:59 AM, Rumen Kostadinov
>    >> <rkostadi at gmail.com> wrote:
>    >>> Dear all,
>    >>>
>    >>> I found a bug in the which() function.
>    >>>
>    >>> When trying to remove elements with the which function, if the
>    >>> criteria is not matched, numeric(0) is returned instead of the
>    >>> array itself.
>    >>>
>    >>> This is very weird.
>    >>>
>    >>>> a = c(1,2,3,4,5)
>    >>>> a[!a==6]
>    >>> [1] 1 2 3 4 5
>    >>>> a[-which(a==6)]
>    >>> numeric(0)
>    >>>> a[-which(a==5)]
>    >>> [1] 1 2 3 4
>    >>>> a[!a==5]
>    >>> [1] 1 2 3 4
>    >>>
>    >>> Is this correct? I believe this is a bug.
>    >>>
>    >>> I have to rewrite a lot of my R code to use
>    >>> a = a[!criteria]
>    >>> and not
>    >>> a = a[-which(criteria)]
>    >>>
>    >>> R.
>    >>>
>    >>
>    >>
>    >> --
>    >> Sarah Goslee
>    >> http://www.functionaldiversity.org
>    >>
>
>    RK> ______________________________________________ RK>
>    R-help at r-project.org mailing list RK>
>    https://stat.ethz.ch/mailman/listinfo/r-help RK> PLEASE do read
>    the posting guide http://www.R-project.org/posting-guide.html RK>
>    and provide commented, minimal, self-contained, reproducible code.
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>



More information about the R-help mailing list