[R] General indexing in multidimensional arrays

Jannis bt_jannis at yahoo.de
Thu Aug 4 23:54:21 CEST 2011


Your function only works for the first dimensions (e.g. indices 
indicating the positions in the first two dimensions in datacube), correct?

Otherwise it looks very handy! And certainly more elegent than my 
function monster!

Jannis

On 08/04/2011 09:58 PM, R. Michael Weylandt wrote:
> Hi Jannis,
>
> Like Gene, I'm not entirely sure what your code is intended to do, but it
> wasn't hard to adapt mine to at least print out the desired slice through
> the higher-dimensional array:
>
> cubeValues<- function(Insert, Destination, Location) {
>      Location = as.matrix(Location)
>      Location = array(Location,dim(Destination))
>      if (is.null(Insert)) {
>          Destination = round(Destination,3)
>          Destination[!Location] = NA
>          print(Destination)
>          return(invisible())
>      }
>      Destination[Location]<- Insert
>      return(Destination)
> }
>
> If Insert = NULL, it adopts a printing rather than value assigning behavior.
>
>
> If you could indicate how you want the values when they come out, it's
> pretty easy to adapt this to do whatever, but I can't just pull out
> subarrays of arbitrary shape while keeping shape: e.g.,
>
> x = matrix(1:4,2,2,byrow=T)
> y = rbind(c(T,F),c(F,T))
>
>> is(x[y])
> "vector"
>
> If you just want the values in a vector, take this version of my code:
>
> cubeValues<- function(Insert, Destination, Location) {
>      Location = as.matrix(Location)
>      Location = array(Location,dim(Destination))
>      if (is.null(Insert)) {
>          return(Destination[Location])
>      }
>      Destination[Location]<- Insert
>      return(Destination)
> }
>
> It sounds like you've got what you want, but hopefully this will be of some
> use to anyone who stumbles across this and, like Gene&  myself, doesn't
> really get your code.
>
> NB: I have not tested the provided code very much -- it relies on the
> array() function to repeat Location as appropriate. If you know how R
> repeats smaller arrays to make them fit big arrays, this should be fine for
> you -- caveat code-or.
>
> Michael Weylandt
>
> PS -- The combinations() function of the gtools package might be of help to
> you as well. We could get the entire example Gene got by
>
> ans =  combinations(1:4,2,repeats.allowed=T)
> rbind(cbind(ans,4),cbind(ans,1))
>
> and it's probably not hard to simplify the entire code as desired.
>
> On Thu, Aug 4, 2011 at 6:33 AM, Jannis<bt_jannis at yahoo.de>  wrote:
>
>> Thanks, Michael. I was, however, after a function I coul use for both
>> extracting and replacing subarrays. In case anybody else stumbles over this
>> problem, here is my solution. Its programming is most probably horribly
>> clumsy:
>>
>>
>> ind.datacube = function(
>> ##title<<  create logical index matrices for multidimensional datacubes
>>   datacube       ##<<  array: datacube from which to extract the subparts
>>   , logical.ind  ##<<  logical array: TRUE/FALSE index matrix for a subset of
>> the dimensions
>>                  ##   of datacube. The size of logical.ind`s dimesnions has
>> to match the
>>                  ##   sizes of the corresponding dimesnions in datacube.
>>   , dims='auto'  ##<<  integer vector or 'auto' : indices of the dimensions
>> in datacube corresponding
>>                  ##   to the dimensions of logical.ind. If set to 'auto'
>> this matching is tried to
>>                  ##   be accomplished by comparing the sizes of the
>> dimensions of the two objects.
>> )
>> {
>>     if (sum(logical.ind) == 0) {
>>         stop('No TRUE value in index matrix!')
>>     } else {
>>         if (dims == 'auto')
>>         {
>>             if (is.null(dim(logical.ind)[1])) {
>>                 size.ind     = length(logical.ind)
>>                 logical.ind  = matrix(logical.ind,ncol=1)
>>             } else {
>>                 size.ind = dim(logical.ind)
>>             }
>>             dims = match(size.ind, dim(datacube))
>>             if (sum(duplicated(size.ind))>  0 || sum(duplicated(dims))>  0 )
>>                 stop('dimensions do not match unambigously. Supply dims
>> manually!')
>>         }
>>         dims.nonapply<- setdiff(1:length(dim(datacube)**),dims)
>>         ind.matrix<- which(logical.ind, arr.ind = TRUE)
>>
>>         args.expand.grid<- list()
>>         counter = 1
>>         for (i in 1: length(dim(datacube)))
>>         {
>>             if (is.element(i,dims.nonapply)) {
>>                 args.expand.grid[[i]] = 1:dim(datacube)[dims.nonapply[**i]]
>>             } else {
>>                 args.expand.grid[[i]] = ind.matrix[,counter]
>>                 counter = counter + 1
>>             }
>>         }
>>
>>         ind.all<- as.matrix(do.call(expand.grid, args.expand.grid))
>>         ind.matrix<- ind.all[,order(c(dims.**nonapply,dims))]
>>
>>     }
>>     ##value<<  integer index matrix which can be used to index datacube
>>     ind.matrix
>>
>> }
>>
>>
>> On 08/04/2011 12:12 AM, R. Michael Weylandt<michael.weylandt at gmail.com>
>> wrote:
>>
>>>   This might be a little late: but how about this (slightly clumsy)
>>>> function:
>>>>
>>>> putValues<- function(Insert, Destination, Location) {
>>>>      Location = as.matrix(Location)
>>>>      Location = array(Location,dim(**Destination))
>>>>      Destination[Location]<- Insert
>>>>      return(Destination)
>>>> }
>>>>
>>>> It currently assumes that the location array lines up in dimension order,
>>>> but other than that seems to work pretty well. If you want, it shouldn't
>>>> be
>>>> hard to change it to take in a set of dimensions to arrange Location
>>>> along.
>>>> If you like any of the other suggested behaviors, you could put in a
>>>> is.null(Insert) option that returns the desired subset of values. I
>>>> haven't
>>>> tested it completely, but for a few sample inputs, it seems be do as
>>>> desired.
>>>>
>>>> Michael
>>>>
>>>>
>>>> On Wed, Aug 3, 2011 at 5:00 PM, Jannis<bt_jannis at yahoo.de>   wrote:
>>>>
>>>>   Thanks for all the replies!Unfortunately the solutions only work for
>>>>> extracting subsets of the data (which was exactly what I was asking for)
>>>>> and
>>>>> not to replace subsets with other values. I used them, however, to
>>>>> program a
>>>>> rather akward function to do that. Seems I found one of the few aspects
>>>>> where Matlab actually is slightly easier to use than R.
>>>>>
>>>>>
>>>>> Thanks for your help!
>>>>> Jannis
>>>>>
>>>>> On 08/01/2011 05:50 PM, Gene Leynes wrote:
>>>>>
>>>>>   What do you think about this?
>>>>>> apply(data, 3, '[', indices)
>>>>>>
>>>>>>
>>>>>> On Mon, Aug 1, 2011 at 4:38 AM, Jannis<bt_jannis at yahoo.de>    wrote:
>>>>>>
>>>>>>   Dear R community,
>>>>>>
>>>>>>> I have a general question regarding indexing in multidiemensional
>>>>>>> arrays.
>>>>>>>
>>>>>>> Imagine I have a three dimensional array and I only want to extract on
>>>>>>> vector along a single dimension from it:
>>>>>>>
>>>>>>>
>>>>>>> data<- array(rnorm(64),dim=c(4,4,4))
>>>>>>>
>>>>>>> result<- data[1,1,]
>>>>>>>
>>>>>>> If I want to extract more than one of these vectors, it would now
>>>>>>> really
>>>>>>> help me to supply a logical matrix of the size of the first two
>>>>>>> dimensions:
>>>>>>>
>>>>>>>
>>>>>>> indices<- matrix(FALSE,ncol=4,nrow=4)
>>>>>>> indices[1,3]<- TRUE
>>>>>>> indices[4,1]<- TRUE
>>>>>>>
>>>>>>> result<- data[indices,]
>>>>>>>
>>>>>>> This, however would give me an error. I am used to this kind of
>>>>>>> indexing
>>>>>>> from Matlab and was wonderingt whether there exists an easy way to do
>>>>>>> this
>>>>>>> in R without supplying complicated index matrices of all three
>>>>>>> dimensions or
>>>>>>> logical vectors of the size of the whole matrix?
>>>>>>>
>>>>>>> The only way I could imagine would be to:
>>>>>>>
>>>>>>> result<- data[rep(as.vector(indices),******times=4)]
>>>>>>>
>>>>>>> but this seems rather complicated and also depends on the order of the
>>>>>>> dimensions I want to extract.
>>>>>>>
>>>>>>>
>>>>>>> I do not want R to copy Matlabs behaviour, I am just wondering whether
>>>>>>> I
>>>>>>> missed one concept of indexing in R?
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Thanks a lot
>>>>>>> Jannis
>>>>>>>
>>>>>>> ______________________________******________________
>>>>>>> R-help at r-project.org mailing list
>>>>>>> https://stat.ethz.ch/mailman/******listinfo/r-help<https://stat.ethz.ch/mailman/****listinfo/r-help>
>>>>>>> <https://**stat.ethz.ch/mailman/****listinfo/r-help<https://stat.ethz.ch/mailman/**listinfo/r-help>
>>>>>>> <https://stat.**ethz.ch/**mailman/listinfo/r-**help<http://ethz.ch/mailman/listinfo/r-**help>
>>>>>>> <http**s://stat.ethz.ch/mailman/**listinfo/r-help<https://stat.ethz.ch/mailman/listinfo/r-help>
>>>>>>> PLEASE do read the posting guide http://www.R-project.org/**
>>>>>>> posting-guide.html<http://www.****R-project.org/posting-guide.**
>>>>>>> **html<http://www.R-project.**org/posting-guide.html<http://www.R-project.org/posting-guide.html>
>>>>>>> and provide commented, minimal, self-contained, reproducible code.
>>>>>>>
>>>>>>>
>>>>>>>   ______________________________****________________
>>>>> R-help at r-project.org mailing list
>>>>> https://stat.ethz.ch/mailman/****listinfo/r-help<https://stat.ethz.ch/mailman/**listinfo/r-help>
>>>>> <https://stat.**ethz.ch/mailman/listinfo/r-**help<https://stat.ethz.ch/mailman/listinfo/r-help>
>>>>> PLEASE do read the posting guide http://www.R-project.org/**
>>>>> posting-guide.html<http://www.**R-project.org/posting-guide.**html<http://www.R-project.org/posting-guide.html>
>>>>> and provide commented, minimal, self-contained, reproducible code.
>>>>>
>>>>>



More information about the R-help mailing list