Skip to content

[Bioc-devel] sapply and vapply

4 messages · Martin Morgan, Henrik Bengtsson, Laurent Gatto

#
Dear all, 

I have a quick question regarding the usage of vapply and sapply. The former is recommended to insure that the output is always a vector of a specific type. For example:
x           y 
  "integer" "character"
$x
[1] "integer"

$y
[1] "POSIXct" "POSIXt"
Error in vapply(df2, class, character(1)) : values must be length 1,
 but FUN(X[[2]]) result is length 2

There are cases, however, were FUN ensures that the output will be of length 1 and of a expected type. For example

- sapply(X, all) - all() always returns logical(1) 
- sapply(X, length) - always numeric(1) (integer(1) or double(1) for vectors of more than 2^31 - 1 elements)

or more generally

- sapply(X, slot, "myslot") - slot() will always return a character(1) because @myslot is always character(1) (as defined by the class)

Would you still recommend to use vapply() in such cases?

Thank you in advance.

Laurent
#
Check the result of sapply(logical(0), all) !

?On 8/12/20, 12:33 PM, "Bioc-devel on behalf of Laurent Gatto" <bioc-devel-bounces at r-project.org on behalf of laurent.gatto at uclouvain.be> wrote:

    Dear all, 

    I have a quick question regarding the usage of vapply and sapply. The former is recommended to insure that the output is always a vector of a specific type. For example:

    > df1 <- data.frame(x = 1:3, y = LETTERS[1:3])     ## OK test
    > df2 <- data.frame(x = 1:3, y = Sys.time() + 1:3) ## Not OK test
    > sapply(df1, class) ## vector of chars, OK
              x           y 
      "integer" "character" 
    > sapply(df2, class) ## ouch, not a vector
    $x
    [1] "integer"

    $y
    [1] "POSIXct" "POSIXt" 

    > vapply(df2, class, character(1)) ## prefer an error rather than a list
    Error in vapply(df2, class, character(1)) : values must be length 1,
     but FUN(X[[2]]) result is length 2

    There are cases, however, were FUN ensures that the output will be of length 1 and of a expected type. For example

    - sapply(X, all) - all() always returns logical(1) 
    - sapply(X, length) - always numeric(1) (integer(1) or double(1) for vectors of more than 2^31 - 1 elements)

    or more generally

    - sapply(X, slot, "myslot") - slot() will always return a character(1) because @myslot is always character(1) (as defined by the class)

    Would you still recommend to use vapply() in such cases?

    Thank you in advance.

    Laurent




    _______________________________________________
    Bioc-devel at r-project.org mailing list
    https://stat.ethz.ch/mailman/listinfo/bioc-devel
#
FWIW,
Actually, the length of length(x) may not be 1L, e.g.
[1] 0 1
"Warning: Package authors have written methods that return a result of
length other than one (Formula) and that return a vector of type
double (Matrix), even with non-integer values (earlier versions of
sets). Where a single double value is returned that can be represented
as an integer it is returned as a length-one integer vector."

I/we recently learned this the hard way
(https://github.com/HenrikBengtsson/future/issues/395).  It's rather
unfortunate that not even length() is strictly defined here, I'd say.
I think we could move away from this if lengths() would be a generic
so lengths(x) could be used above.  But that's a discussion for
R-devel.

/Henrik


On Wed, Aug 12, 2020 at 9:33 AM Laurent Gatto
<laurent.gatto at uclouvain.be> wrote:
#
Thank you for these instructive, although somewhat disheartening clarifications.

Laurent