Forgive me if this has been asked many times before, but I couldn't find anything on the mailing lists. I'd expect apply(m, 1, foo) not to call `foo` if m is a matrix with zero rows. In fact: m <- matrix(NA, 0, 5) apply(m, 1, function (x) {cat("Called...\n"); print(x)}) ## Called... ## [1] FALSE FALSE FALSE FALSE FALSE Similarly for apply(m, 2,...) if m has no columns. Is there a reason for this? Could it be documented? David -- Sent from Gmail Mobile [[alternative HTML version deleted]]
>>>>> David Hugh-Jones >>>>> on Mon, 30 Jul 2018 05:33:19 +0100 writes:> Forgive me if this has been asked many times before, but I > couldn't find anything on the mailing lists. > I'd expect apply(m, 1, foo) not to call `foo` if m is a > matrix with zero rows. In fact: > m <- matrix(NA, 0, 5) > apply(m, 1, function (x) {cat("Called...\n"); print(x)}) > ## Called... > ## [1] FALSE FALSE FALSE FALSE FALSE > Similarly for apply(m, 2,...) if m has no columns. Is > there a reason for this? Yes : The reverse is really true for almost all basic R functions: They *are* called and give an "empty" result automatically when the main argument is empty. What you basicaly propose is to add an extra if(<length 0 input>) return(<correspondingly formatted length-0 output>) to all R functions. While that makes sense for high-level R functions that do a lot of things, this would really be a bad idea in general : This would make all of these basic functions larger {more to maintain} and slightly slower for all non-zero cases just to make them slightly faster for the rare zero-length case. Martin Maechler ETH Zurich and R core Team
Hi Martin, Fair enough for R functions in general. But the behaviour of apply violates the expectation that apply(m, 1, fun) calls fun n times when m has n rows. That seems pretty basic. Also, I understand from your argument why it makes sense to call apply and return a special result (presumably NULL) for an empty argument; but why should apply call fun? Cheers David On Mon, 30 Jul 2018 at 08:41, Martin Maechler <maechler at stat.math.ethz.ch> wrote:> >>>>> David Hugh-Jones > >>>>> on Mon, 30 Jul 2018 05:33:19 +0100 writes: > > > Forgive me if this has been asked many times before, but I > > couldn't find anything on the mailing lists. > > > I'd expect apply(m, 1, foo) not to call `foo` if m is a > > matrix with zero rows. In fact: > > > m <- matrix(NA, 0, 5) > > apply(m, 1, function (x) {cat("Called...\n"); print(x)}) > > ## Called... > > ## [1] FALSE FALSE FALSE FALSE FALSE > > > > Similarly for apply(m, 2,...) if m has no columns. Is > > there a reason for this? > > Yes : > > The reverse is really true for almost all basic R functions: > > They *are* called and give an "empty" result automatically > when the main argument is empty. > > What you basicaly propose is to add an extra > > if(<length 0 input>) > return(<correspondingly formatted length-0 output>) > > to all R functions. While that makes sense for high-level R > functions that do a lot of things, this would really be a bad > idea in general : > > This would make all of these basic functions larger {more to maintain} and > slightly slower for all non-zero cases just to make them > slightly faster for the rare zero-length case. > > Martin Maechler > ETH Zurich and R core Team > > --Sent from Gmail Mobile [[alternative HTML version deleted]]
Hi David, Besides Martins point, there is also the issue that for a lot of cases you would still like to have the right class returned. Right now these are returns: > apply(matrix(NA_integer_,0,5), 1, class) character(0) > apply(matrix(NA_integer_,0,5), 1, identity) integer(0) > apply(matrix(NA,0,5), 1, identity) logical(0) In your case, these would all return NULL, so I think there is value in running FUN at least once (Say if you'd want to check if FUN always returns the right class). And from a philosophical point of view, R is mostly a functional programming language, I think if you want side-effects a for-loop would look better. Best regards, Emil Bode Data-analyst +31 6 43 83 89 33 emil.bode at dans.knaw.nl DANS: Netherlands Institute for Permanent Access to Digital Research Resources Anna van Saksenlaan 51 | 2593 HW Den Haag | +31 70 349 44 50 | info at dans.knaw.nl <mailto:info at dans.kn> | dans.knaw.nl <applewebdata://71F677F0-6872-45F3-A6C4-4972BF87185B/www.dans.knaw.nl> DANS is an institute of the Dutch Academy KNAW <http://knaw.nl/nl> and funding organisation NWO <http://www.nwo.nl/>. On 30/07/2018, 11:12, "R-devel on behalf of David Hugh-Jones" <r-devel-bounces at r-project.org on behalf of davidhughjones at gmail.com> wrote: Hi Martin, Fair enough for R functions in general. But the behaviour of apply violates the expectation that apply(m, 1, fun) calls fun n times when m has n rows. That seems pretty basic. Also, I understand from your argument why it makes sense to call apply and return a special result (presumably NULL) for an empty argument; but why should apply call fun? Cheers David On Mon, 30 Jul 2018 at 08:41, Martin Maechler <maechler at stat.math.ethz.ch> wrote: > >>>>> David Hugh-Jones > >>>>> on Mon, 30 Jul 2018 05:33:19 +0100 writes: > > > Forgive me if this has been asked many times before, but I > > couldn't find anything on the mailing lists. > > > I'd expect apply(m, 1, foo) not to call `foo` if m is a > > matrix with zero rows. In fact: > > > m <- matrix(NA, 0, 5) > > apply(m, 1, function (x) {cat("Called...\n"); print(x)}) > > ## Called... > > ## [1] FALSE FALSE FALSE FALSE FALSE > > > > Similarly for apply(m, 2,...) if m has no columns. Is > > there a reason for this? > > Yes : > > The reverse is really true for almost all basic R functions: > > They *are* called and give an "empty" result automatically > when the main argument is empty. > > What you basicaly propose is to add an extra > > if(<length 0 input>) > return(<correspondingly formatted length-0 output>) > > to all R functions. While that makes sense for high-level R > functions that do a lot of things, this would really be a bad > idea in general : > > This would make all of these basic functions larger {more to maintain} and > slightly slower for all non-zero cases just to make them > slightly faster for the rare zero-length case. > > Martin Maechler > ETH Zurich and R core Team > > -- Sent from Gmail Mobile [[alternative HTML version deleted]] ______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Try pmap and related functions in purrr: pmap(as.data.frame(m), ~ { cat("Called...\n"); print(c(...)) }) ## list() On Mon, Jul 30, 2018 at 12:33 AM, David Hugh-Jones <davidhughjones at gmail.com> wrote:> Forgive me if this has been asked many times before, but I couldn't find > anything on the mailing lists. > > I'd expect apply(m, 1, foo) not to call `foo` if m is a matrix with zero > rows. > In fact: > > m <- matrix(NA, 0, 5) > apply(m, 1, function (x) {cat("Called...\n"); print(x)}) > ## Called... > ## [1] FALSE FALSE FALSE FALSE FALSE > > Similarly for apply(m, 2,...) if m has no columns. > Is there a reason for this? Could it be documented? > > David > -- > Sent from Gmail Mobile > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel-- Statistics & Software Consulting GKX Group, GKX Associates Inc. tel: 1-877-GKX-GROUP email: ggrothendieck at gmail.com
Interesting discussion. I'm not wholly convinced by Martin's and Emil's arguments. The behaviour seems to violate an obvious expectation (fun is called once per row) to satisfy a subtle one (result has a guaranteed dimension and type). In any case, here's a suggested chunk of rd to go at the end of the "Value": If \code{dim(X)[MARGIN]} is zero, then \code{FUN} is called once, with an argument of the appropriate dimensions. The argument's type is the same as \code{typeof(m)}, and the argument values are those returned by \code{vector(typeof(m))}. For example, if m is numeric, the argument will be a vector (or matrix or array) of zeroes. The type and length of the value returned by \code{FUN} is used to determine the type of the result. And at the end of "Details": \code{FUN} is always called at least once, see below. David On Mon, 30 Jul 2018 at 15:05, Gabor Grothendieck <ggrothendieck at gmail.com> wrote:> Try pmap and related functions in purrr: > > pmap(as.data.frame(m), ~ { cat("Called...\n"); print(c(...)) }) > ## list() > > On Mon, Jul 30, 2018 at 12:33 AM, David Hugh-Jones > <davidhughjones at gmail.com> wrote: > > Forgive me if this has been asked many times before, but I couldn't find > > anything on the mailing lists. > > > > I'd expect apply(m, 1, foo) not to call `foo` if m is a matrix with zero > > rows. > > In fact: > > > > m <- matrix(NA, 0, 5) > > apply(m, 1, function (x) {cat("Called...\n"); print(x)}) > > ## Called... > > ## [1] FALSE FALSE FALSE FALSE FALSE > > > > Similarly for apply(m, 2,...) if m has no columns. > > Is there a reason for this? Could it be documented? > > > > David > > -- > > Sent from Gmail Mobile > > > > [[alternative HTML version deleted]] > > > > ______________________________________________ > > R-devel at r-project.org mailing list > > https://stat.ethz.ch/mailman/listinfo/r-devel > > > > -- > Statistics & Software Consulting > GKX Group, GKX Associates Inc. > tel: 1-877-GKX-GROUP > email: ggrothendieck at gmail.com >[[alternative HTML version deleted]]