r-lib / rray

Simple Arrays
https://rray.r-lib.org
GNU General Public License v3.0
130 stars 12 forks source link

Rray generating functions #215

Open juangomezduaso opened 5 years ago

juangomezduaso commented 5 years ago

I think it could be useful to generate rrays from a function over its indexes. To illustrate and brainstorm this idea I have made some alternatives for you to taste it.

library(rray)
#> Warning: package 'rray' was built under R version 3.5.3
# A user friendly version:
rray_formula <- function(dimen, formula){
  names<- names(dimen)
  stopifnot(!is.null(names) )
  e <- rlang::enquo(formula)
  seqs <- purrr::map(as.list(dimen), function(i)1:i)
  frame <- expand.grid(seqs)
  cells<- rlang::eval_tidy(e, data = frame)
  rray(cells, dimen)
}
(rray_formula(c(a=2,b=3),a+b^2) )
#> <rray<dbl>[,3][6]>
#>      [,1] [,2] [,3]
#> [1,]    2    5   10
#> [2,]    3    6   11
(rray_formula(c(x=2,y=3),ifelse(x >= y, 1,0)) )
#> <rray<dbl>[,3][6]>
#>      [,1] [,2] [,3]
#> [1,]    1    0    0
#> [2,]    1    1    0

# A sligthly more verbose alternative:
rray_pmap <- function(dimen,fun){
  seqs <- purrr::map(as.list(dimen), function(i)1:i)
  frame <- expand.grid(seqs)
  l <- as.list(frame)
  names(l)<-NULL
  cells <- purrr::pmap_dbl(l,fun)
  rray(cells, dimen)
}
(rray_pmap(c(2,3), function(x,y)x+y^2) )
#> <rray<dbl>[,3][6]>
#>      [,1] [,2] [,3]
#> [1,]    2    5   10
#> [2,]    3    6   11
(rray_pmap(c(2,3),function(x,y)if(x >= y)1 else 0) )
#> <rray<dbl>[,3][6]>
#>      [,1] [,2] [,3]
#> [1,]    1    0    0
#> [2,]    1    1    0

# A different one, where all indexes go  as a single vector:
rray_vmap <- function(dimen,fun){
  seqs <- purrr::map(as.list(dimen), function(i)1:i)
  matrix <- t(expand.grid(seqs))
  l <- purrr::array_branch(matrix,margin=2)
  cells <- purrr::map_dbl(l,fun)
  rray(cells, dimen)
}
(rray_vmap(c(2,3), function(v) v[1]+v[2]^2) )
#> <rray<dbl>[,3][6]>
#>      [,1] [,2] [,3]
#> [1,]    2    5   10
#> [2,]    3    6   11
(rray_vmap(c(2,3),function(v)if(v[1] >= v[2])1 else 0) )
#> <rray<dbl>[,3][6]>
#>      [,1] [,2] [,3]
#> [1,]    1    0    0
#> [2,]    1    1    0

# The last one is less apealing, but far more useful for programming
# As an example, here is a quick rray_shift() implementation based on it:

rray_shift <-function(x,axis,n){
  rray_vmap(dim(x), function(v) 
    if(v[axis]>n){
      l<-as.list(v)
      l[[axis]]<-l[[axis]]-n
      do.call(`[`,c(list(x),l))
    } else NA)
}
rr=rray(1:6,2:3)  
( rray_shift(rr,2,1)  )
#> <rray<dbl>[,3][6]>
#>      [,1] [,2] [,3]
#> [1,]   NA    1    3
#> [2,]   NA    2    4

Created on 2019-06-12 by the reprex package (v0.2.1)

juangomezduaso commented 5 years ago

An interesting (but perhaps too weird) alternative to these functions would be to have an S3 class of "virtual rrays", consisting of just the function and probaby the dimensionality , but not any concrete dimension. These "vrrays" would operate between themselves (virtually, to yield another vrray having , for example , (A+B)$fun = function(v) A$fun(v) +B$fun(v). And would operate with (a)rrays instantiating a compatible rray with the functions above (with broadcasting included) and yielding a rray as the result. Other functions like reshape, transpose, etc would also be easy to define, returning modified virtual rrays . OTOH, subseting would return a "real" rray. Functions like rray_yank(), rray_sum() etc would have no sense in these "infinite rrays" . Not the case of dim(x) which could, obviously, return: rep(Inf, rray_dims(x) ) ;)