Re: [Rd] aperm() should retain class of input object

2010-12-28 Thread Tim Hesterberg
Having aperm() return an object of the same class is dangerous, there
are undoubtedly classes for which that is not appropriate, producing an
illegal object for that class or quietly giving incorrect results.

Three alternatives are to:
* add the keep.class option but with default FALSE
* make aperm a generic function 
  - without a keep.class argument
  - with a ... argument
  - methods for classes like table could have keep.class = TRUE
* make aperm a generic function 
  - without a keep.class argument
  - with a ... argument
  - default method have keep.class = TRUE

The third option would give the proposed behavior by default, but
allow a way out for classes where the behavior is wrong.  This puts
the burden on a class author to realize the potential problem with
aperm, so my preference is one of the first two options.

aperm() was designed for multidimensional arrays, but is also useful for
table objects, particularly
with the lattice, vcd and vcdExtra packages.  But aperm() was designed
and implemented before other
related object classes were conceived, and I propose a small tune-up to
make it more generally useful.

The problem is that  aperm() always returns an object of class 'array',
which causes problems for methods
designed for table objects. It also requires some package writers to
implement both .array and .table
methods for the same functionality, usually one in terms of the other.
Some examples of unexpected, and initially perplexing results (when only
methods for one class are implemented)
are shown below.


  library(vcd)
  pairs(UCBAdmissions, shade=TRUE)
  UCB - aperm(UCBAdmissions, c(2, 1, 3))
 
  # UCB is now an array, not a table
  pairs(UCB, shade=TRUE)
There were 50 or more warnings (use warnings() to see the first 50)
 
  # fix it, to get pairs.table
  class(UCB) - table
  pairs(UCB, shade=TRUE)
 



Of course, I can define a new function, tperm() that does what I think
should be the expected behavior:

# aperm, for table objects

tperm - function(a, perm, resize = TRUE) {
 result - aperm(a, per, resize)
 class(result) - class(a)
 result
}

But I think it is more natural to include this functionality in aperm()
itself.  Thus, I propose the following
revision of base::aperm(), at the R level:

aperm - function (a, perm, resize = TRUE, keep.class=TRUE)
{
 if (missing(perm))
 perm - integer(0L)
 result - .Internal(aperm(a, perm, resize))
 if(keep.class) class(result) - class(a)
 result
}


I don't think this would break any existing code, except where someone
depended on coercion to an array.
The drop-in replacement for aperm would set keep.class=FALSE by default,
but I think TRUE is  more
natural.

FWIW, here are the methods for table and array objects
from my current (non-representative) session.

  methods(class=table)
  [1] as.data.frame.table barchart.table* cloud.table*
contourplot.table*  dotplot.table*
  [6] head.table* levelplot.table*pairs.table*
plot.table* print.table
[11] summary.table   tail.table*

Non-visible functions are asterisked
 
  methods(class=array)
[1] anyDuplicated.array as.data.frame.array as.raster.array*
barchart.array* contourplot.array*  dotplot.array*
[7] duplicated.arraylevelplot.array*unique.array


--
Michael Friendly Email: friendly AT yorku DOT ca
Professor, Psychology Dept.
York University  Voice: 416 736-5115 x66249 Fax: 416 736-5814
4700 Keele StreetWeb:http://www.datavis.ca
Toronto, ONT  M3J 1P3 CANADA

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] RFC: sapply() limitation from vector to matrix, but not further

2010-12-28 Thread Martin Maechler
 Gabor Grothendieck ggrothendi...@gmail.com
 on Mon, 27 Dec 2010 17:06:25 -0500 writes:

 On Wed, Dec 1, 2010 at 3:39 AM, Martin Maechler
 maech...@stat.math.ethz.ch wrote:
 My proposal -- implemented and make check tested -- is
 to add an optional argument  'ARRAY' which allows
 
 sapply(v, myF, y = 2*(1:5), ARRAY=TRUE)

 It would reduce the proliferation of arguments if the
 simplify= argument were extended to allow this,
 e.g. simplify = array or perhaps simplify = n would
 allow a maximum of n dimensions.

That's a good idea, though it makes the
implementation/documentation very slightly more complicated.

I'm interested to get more feedback on my other questions,
notably the only about *changing*  vapply() (on the C-level) to
behave logical in the sense of adding one  dim(.)ension in
those cases, the FUN.VALUE (result prototype) has a dim().


Martin

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] RFC: sapply() limitation from vector to matrix, but not further

2010-12-28 Thread Tony Plate

The abind() function from the abind package is an alternative here -- it can 
take a list argument, which makes it easy to use with the result of lapply().  
It's also able take direction about which dimension to join on.

 x - list(a=1,b=2,c=3)
 f - function(v) matrix(v, nrow=2, ncol=4)
 sapply(x, f)
 a b c
[1,] 1 2 3
[2,] 1 2 3
[3,] 1 2 3
[4,] 1 2 3
[5,] 1 2 3
[6,] 1 2 3
[7,] 1 2 3
[8,] 1 2 3

 # The 'along=' argument to abind() determines on which dimension
 # the list elements are joined.  Use a fractional value to put the new
 # dimension between existing ones.

 dim(abind(lapply(x, f), along=0))
[1] 3 2 4
 dim(abind(lapply(x, f), along=1.5))
[1] 2 3 4
 dim(abind(lapply(x, f), along=3))
[1] 2 4 3
 abind(lapply(x, f), along=3)
, , a

 [,1] [,2] [,3] [,4]
[1,]1111
[2,]1111

, , b

 [,1] [,2] [,3] [,4]
[1,]2222
[2,]2222

, , c

 [,1] [,2] [,3] [,4]
[1,]3333
[2,]3333



On 12/28/2010 8:49 AM, Martin Maechler wrote:

Gabor Grothendieckggrothendi...@gmail.com
 on Mon, 27 Dec 2010 17:06:25 -0500 writes:

   On Wed, Dec 1, 2010 at 3:39 AM, Martin Maechler
   maech...@stat.math.ethz.ch  wrote:
   My proposal -- implemented and make check tested -- is
   to add an optional argument  'ARRAY' which allows
 
   sapply(v, myF, y = 2*(1:5), ARRAY=TRUE)

   It would reduce the proliferation of arguments if the
   simplify= argument were extended to allow this,
   e.g. simplify = array or perhaps simplify = n would
   allow a maximum of n dimensions.

That's a good idea, though it makes the
implementation/documentation very slightly more complicated.

I'm interested to get more feedback on my other questions,
notably the only about *changing*  vapply() (on the C-level) to
behave logical in the sense of adding one  dim(.)ension in
those cases, the FUN.VALUE (result prototype) has a dim().


Martin

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] rJava question

2010-12-28 Thread Simon Urbanek
Dominick,

On Dec 27, 2010, at 11:56 PM, Dominick Samperi wrote:

 After some trial and error I figured out how to pass matrices from R to java
 and back using rJava, but this method is not documented and I wonder if there 
 is a
 better way?
 

stats-rosuda-devel is the rJava list you want to use.


 Anyway, here is what I found works:
 
 (m = matrix(as.double(1:12),3,4))
 [shows m as you would expect]
 
 jtest - .jnew(JTest)
 (v - .jcall(jtest, '[[D], 'myfunc', .jarray(m), evalArray=FALSE))
 [shows v = m + 10]
 
 Here the JTest class has a method named myfunc that accepts
 a double[][] and returns a double[][]. It simply adds 10 to every
 element.
 

The above is plain wrong (well, that's actually a guess since you didn't 
provide even the signature of the method) - matrices in R are vectors, so the 
type is double[]. In Java there is no matrix type, so it's up to the 
application to represent matrices and there are many ways - some more efficient 
than others. From your example above it seems that you are using double[][] -- 
so you have to allocate the extra objects one way or another (that's why it's 
inefficient to represent matrices that way).

But from your e-mail I have the feeling that your questions is rather about 
calling a method that returns double[][], so for example:
public static double[][] pass();
where double[][] is a rectangular array (i.e. length of all inner arrays is 
equal).

Unfortunately .jcall is a bit inconsistent due to bug that was introduced with 
the new J() API. So the intended behavior is (using class Test with the method 
above):
 J(Test)$pass()
 [,1] [,2] [,3] [,4]
[1,]1234
[2,]5678
[3,]9   10   11   12
[4,]   13   14   15   16

The $ operator makes sure that the result is converted to a native R form where 
possible, including recursive structures like double[][].

However, the intention of .jcall() was to never perform recursive evaluation, 
so this is intended:

 .jcall(Test,[[D,pass, evalArray=TRUE)
[[1]]
[1] Java-Array-Object[D:[...@11ddcde

[[2]]
[1] Java-Array-Object[D:[...@18fb1f7

[[3]]
[1] Java-Array-Object[D:[...@ed0338

[[4]]
[1] Java-Array-Object[D:[...@6e70c7


The intended behavior (and true in older version of rJava) was for .jcall with 
evalArray=FALSE to return the reference:

 .jcall(Test,[[D,pass, evalArray=FALSE)
[1] Java-Array-Object[[D:[...@8f4fb3

Unfortunately, the bug is that .jcall uses rJava:::newArray() to create the 
reference which defaults to simplify=TRUE so the current (buggy) behavior is:

 .jcall(Test,[[D,pass, evalArray=FALSE)
 [,1] [,2] [,3] [,4]
[1,]1234
[2,]5678
[3,]9   10   11   12
[4,]   13   14   15   16


The real issue is that:
a) if the bug is fixed, .jcall() can return just the reference which is intended
but
b) there is currently no exposed API for rJava:::newArray so the simplification 
is not available in any form for references if the bug is fixed (other than 
using the J/$ API).

That's why I was hesitant so far to fix the bug, but I really should -- which 
is why the behavior your discovered will change. However, then I need to add 
some API to be able to convert a reference in the same way that 
rJava:::newArray provides and expose it - I didn't think through that part, so 
that's why I got stuck.

I hope it helps...
Cheers,
Simon

(PS: please continue any discussion on stats-rosuda-devel)


 The parameter 'evalArray' is confusing because when
 evalArray=TRUE the result is NOT evaluated (a list is returned
 that you then have to apply .jevalArray to do get the answer).
 
 There seems to be an option to have a java reference returned
 instead of the actual matrix. Can the R side manipulate the
 matrix (on the java side) through this reference?
 
 Thanks,
 Dominick
 
   [[alternative HTML version deleted]]
 
 __
 R-devel@r-project.org mailing list
 https://stat.ethz.ch/mailman/listinfo/r-devel
 
 

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] RFC: sapply() limitation from vector to matrix, but not further

2010-12-28 Thread Martin Maechler
On Tue, Dec 28, 2010 at 19:14, Tony Plate tpl...@acm.org wrote:
 The abind() function from the abind package is an alternative here -- it can
 take a list argument, which makes it easy to use with the result of
 lapply().  It's also able take direction about which dimension to join on.

 x - list(a=1,b=2,c=3)
 f - function(v) matrix(v, nrow=2, ncol=4)
 sapply(x, f)
     a b c
 [1,] 1 2 3
 [2,] 1 2 3
 [3,] 1 2 3
 [4,] 1 2 3
 [5,] 1 2 3
 [6,] 1 2 3
 [7,] 1 2 3
 [8,] 1 2 3

 # The 'along=' argument to abind() determines on which dimension
 # the list elements are joined.  Use a fractional value to put the new
 # dimension between existing ones.

 dim(abind(lapply(x, f), along=0))
 [1] 3 2 4
 dim(abind(lapply(x, f), along=1.5))
 [1] 2 3 4
 dim(abind(lapply(x, f), along=3))
 [1] 2 4 3
 abind(lapply(x, f), along=3)
 , , a

     [,1] [,2] [,3] [,4]
 [1,]    1    1    1    1
 [2,]    1    1    1    1

 , , b

     [,1] [,2] [,3] [,4]
 [1,]    2    2    2    2
 [2,]    2    2    2    2

 , , c

     [,1] [,2] [,3] [,4]
 [1,]    3    3    3    3
 [2,]    3    3    3    3


Thank you, Tony.
Indeed, yes,  abind() is nice here (and in the good ol' APL spirit !)

Wanting to keep things both simple *and* fast here, of course,
hence I currently contemplate the following code,
where the new  simplify2array()  is  considerably simpler than  abind():

##' Simplify a list of commonly structured components into an array.
##'
##' @title simplify list() to an array if the list elements are
structurally equal
##' @param x a list, typically resulting from lapply()
##' @param higher logical indicating if an array() of higher rank
##'  should be returned when appropriate, namely when all elements of
##' \code{x} have the same \code{\link{dim}()}ension.
##' @return x itself, or an array if the simplification is sensible
simplify2array - function(x, higher = TRUE)
{
if(length(common.len - unique(unlist(lapply(x, length  1L)
return(x)
if(common.len == 1L)
unlist(x, recursive = FALSE)
else if(common.len  1L) {
n - length(x)
## make sure that array(*) will not call rep() {e.g. for 'call's}:
r - as.vector(unlist(x, recursive = FALSE))
if(higher  length(c.dim - unique(lapply(x, dim))) == 1 
   is.numeric(c.dim - c.dim[[1L]]) 
   prod(d - c(c.dim, n)) == length(r)) {

iN1 - is.null(n1 - dimnames(x[[1L]]))
n2 - names(x)
dnam -
if(!(iN1  is.null(n2)))
c(if(iN1) rep.int(list(n1), length(c.dim)) else n1,
  list(n2)) ## else NULL
array(r, dim = d, dimnames = dnam)

} else if(prod(d - c(common.len, n)) == length(r))
array(r, dim = d,
  dimnames= if(!(is.null(n1 - names(x[[1L]])) 
  is.null(n2 - names(x list(n1,n2))
else x
}
else x
}

sapply - function(X, FUN, ..., simplify = TRUE, USE.NAMES = TRUE)
{
FUN - match.fun(FUN)
answer - lapply(X, FUN, ...)
if(USE.NAMES  is.character(X)  is.null(names(answer)))
names(answer) - X
if(!identical(simplify, FALSE)  length(answer))
simplify2array(answer, higher = (simplify == array))
else answer
}

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


[Rd] \VignetteKeywords{}, for KEYWORDS or for free-tagging?

2010-12-28 Thread Elliot Todd Kleiman

Hi R-devel,

[Question]:

* Is there a KEYWORDS file to lookup 'keywords' to supply
the vignette command, '\VignetteKeywords{}'?

-or, is the pkg writer free to tag the vignette using any
keywords he/she chooses? i.e., free-tagging.

Thank you,

+ Elliot Kleiman
__
San Diego State University
http://www.sdsu.edu/

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel