multi-dimensional list? List of lists? array of lists? - arrays

(I am definitively using wrong terminology in this question, sorry for that - I just don't know the correct way to describe this in R terms...)
I want to create a structure of heterogeneous objects. The dimensions are not necessary rectangular. What I need would be probably called just "array of objects" in other languages like C. By 'object' I mean a structure consisting of different members, i.e. just a list in R - for example:
myObject <- list(title="Uninitialized title", xValues=rep(NA,50), yValues=rep(NA,50))
and now I would like to make 100 such objects, and to be able to address their members by something like
for (i in 1:100) {myObject[i]["xValues"]<-rnorm(50)}
or
for (i in 1:100) {myObject[i]$xValues<-rnorm(50)}
I would be grateful for any hint about where this thing is described.
Thanks in advance!

are you looking for the name of this mythical beast or just how to do it? :) i could be wrong, but i think you'd just call it a list of lists.. for example:
# create one list object
x <- list( a = 1:3 , b = c( T , F ) , d = mtcars )
# create a second list object
y <- list( a = c( 'hi', 'hello' ) , b = c( T , F ) , d = matrix( 1:4 , 2 , 2 ) )
# store both in a third object
z <- list( x , y )
# access x
z[[ 1 ]]
# access y
z[[ 2 ]]
# access x's 2nd object
z[[ 1 ]][[ 2 ]]

I did not realize that you were looking for creating other objects of same structure. You are looking for replicate.
my_fun <- function() {
list(x=rnorm(1), y=rnorm(1), z="bla")
}
replicate(2, my_fun(), simplify=FALSE)
# [[1]]
# [[1]]$x
# [1] 0.3561663
#
# [[1]]$y
# [1] 0.4795171
#
# [[1]]$z
# [1] "bla"
#
#
# [[2]]
# [[2]]$x
# [1] 0.3385942
#
# [[2]]$y
# [1] -2.465932
#
# [[2]]$z
# [1] "bla"

here is the example of solution I have for the moment, maybe it will be useful for somebody:
NUM <- 1000 # NUM is how many objects I want to have
xVal <- vector(NUM, mode="list")
yVal <- vector(NUM, mode="list")
title <- vector(NUM, mode="list")
for (i in 1:NUM) {
xVal[i]<-list(rnorm(50))
yVal[i]<-list(rnorm(50))
title[i]<-list(paste0("This is title for instance #", i))
}
myObject <- list(xValues=xVal, yValues=yVal, titles=title)
# now I can address any member, as needed:
print(myObject$titles[[3]])
print(myObject$xValues[[4]])

If the dimensions are always going to be rectangular (in your case, 100x50), and the contents are always going to be homogeneous (in your case, numeric) then create a 2D array/matrix.
If you want the ability to add/delete/insert on individual lists (or change the data type), then use a list-of-lists.

Related

List comprehensions in NumPy arrays

In essence this is what I want to create
import numpy as np
N = 100 # POPULATION SIZE
D = 30 # DIMENSIONALITY
lowerB = [-5.12] * D # LOWER BOUND (IN ALL DIMENSIONS)
upperB = [5.12] * D # UPPER BOUND (IN ALL DIMENSIONS)
# INITIALISATION PHASE
X = np.empty([N, D]) # EMPTY FLIES ARRAY OF SIZE: (N,D)
# INITIALISE FLIES WITHIN BOUNDS
for i in range(N):
for d in range(D):
X[i, d] = np.random.uniform(lowerB[d], upperB[d])
but I want to do so without the for loops to save time and use List comprehensions
I have try things like
np.array([(x,y)for x in range(N)for y in range(D)])
but this doesn’t get me to an array like array([100,30]). Does anyone know a tutorial or the correct documentation I should be looking at so I can learn exactly how to do this?

R Accessing vector inside list inside Array

I have a very long Array (1955x2417x1) in R where each position stores a list of two vector (named "max" and "min") of length 5.
I would like to find a simple way to create a multidimensional array (dim 1955x2417x5) where each position holds a single value from vector "max"
I have looked at answers such as array of lists in r
but so far without success.
I know I can access the list in each position of the array using
myarray[posX, PosY][[1]][["max"]]
but how to apply that to the whole Array?
SO far I have tried
newArray <- array( unlist(myarray[][[1]][["max"]]), c(1955, 2417, 5))
and
NewArray <-parApply(cl, myarray, c(1:2), function(x) {
a=x[[1]][["max"]]
} )
but the results are not right.
Do you have any suggestion?
Let
e <- list(min = 1:3, max = 4:6)
arr <- array(list(e)[rep(1, 8)], c(2, 4))
dim(arr)
# [1] 2 4
Then one option is
res <- apply(arr, 1:2, function(x) x[[1]][["max"]])
dim(res)
# [1] 3 2 4
and, if the order of dimensions matters,
dim(aperm(res, c(2, 3, 1)))
# [1] 3 2 4

How to create sub-arrays access the i-th dimension of an array within for()?

In a for-loop, I run in i over an array which I would like to sub-index in dimension i. How can this be done? So a minimal example would be
(A <- array(1:24, dim = 2:4))
A[2,,] # i=1
A[,1,] # i=2
A[,,3] # i=3
where I index 'by foot'. I tried something along the lines of this but wasn't successful. Of course one could could create "2,," as a string and then eval & parse the code, but that's ugly. Also, inside the for loop (over i), I could use aperm() to permute the array such that the new first dimension is the former ith, so that I can simply access the first component. But that's kind of ugly too and requires to permute the array back. Any ideas how to do it more R-like/elegantly?
The actual problem is for a multi-dimensional table() object, but I think the idea will remain the same.
Update
I accepted Rick's answer. I just present it with a for loop and simplified it further:
subindex <- c(2,1,3) # in the ith dimension, we would like to subindex by subindex[i]
for(i in seq_along(dim(A))) {
args <- list(1:2, 1:3, 1:4)
args[i] <- subindex[i]
print(do.call("[", c(list(A), args)))
}
#Build a multidimensional array
A <- array(1:24, dim = 2:4)
# Select a sub-array
indexNumber = 2
indexSelection = 1
# Build a parameter list indexing all the elements of A
parameters <- list(A, 1:2, 1:3, 1:4)
# Modify the appropriate list element to a single value
parameters[1 + indexNumber] <- indexSelection
# select the desired subarray
do.call("[", parameters)
# Now for something completely different!
#Build a multidimensional array
A <- array(1:24, dim = 2:4)
# Select a sub-array
indexNumber = 2
indexSelection = 1
reduced <- A[slice.index(A, indexNumber) == indexSelection]
dim(reduced) <- dim(A)[-indexNumber]
# Also works on the left-side
A[slice.index(A, 2)==2] <- -1:-8

"self"-variable for easy referencing in R?

I want to show only parts of an array, that has a long variable name. So far I used:
# Data
k0100_m020_r05_h10000__aea000_aee0$cumsumData = c(-1:10)
# show only parts
k0100_m020_r05_h10000__aea000_aee0$cumsumData[k0100_m020_r05_h10000__aea000_aee0$cumsumData>0]
I wonder if there is a shorter form, since I have to repeat the variable name within the square brackets. Is there a shorter reference to the variable currently used? e.g.:
k0100_m020_r05_h10000__aea000_aee0$cumsumData[_self>0]
Try subset.
subset(k0100_m020_r05_h10000__aea000_aee0, cumsumData > 0)
If you are going to want to look into more than one column an apply approach might be useful:
k0100_m020_r05_h10000__aea000_aee0 <- as.data.frame(matrix(rnorm(25),ncol=5))
apply( k0100_m020_r05_h10000__aea000_aee0 , 2 , function(x) x [ x>0 ] )
#$V1
#[1] 1.5840356 0.2497689
#$V2
#[1] 0.4179352 1.6187143 0.8245239
#$V3
#[1] 0.09328116 0.20761514 0.29894603 2.14484045
#$V4
#[1] 0.4882152 0.4643691 0.5591095
#$V5
#[1] 1.0749748 0.5405291 0.4899797 1.0828021
I am not sure whether this is what you want, but perhaps with() can help:
mask <- with(k0100_m020_r05_h10000__aea000_aee0, _self > 0) # gives you a boolean vector
k0100_m020_r05_h10000__aea000_aee0[mask] # gives you the result

array of lists in r

Suppose if I want to have 10 element array each element is a list/map. I am doing this:
x = array(list(), 10)
x[1][[ "a" ]] = 1
Warning message:
In x[1][["a"]] = 1 :
number of items to replace is not a multiple of replacement length
>
Is this the right approach? I want each element of the array to be a map.
What you're calling an "array" is usually just called a list in R. You're getting tripped up by the difference between [ and [[ for lists. See the section "Recursive (list-like) objects" in help("[").
x[[1]][["a"]] <- 1
UPDATE:
Note that the solution above creates a list of named vectors. In other words, something like
x[[1]][["a"]] <- 1
x[[1]][["b"]] <- 1:2
won't work because you can't assign multiple values to one element of a vector. If you want to be able to assign a vector to a name, you can use a list of lists.
x[[1]] <- as.list(x[[1]])
x[[1]][["b"]] <- 1:2
If you really want to do this, then, because the elements of the lists in each element of the array do not have names, you can't index by a character vector. In your example, there is no x[1][[ "a" ]]:
> x[1][[ "a" ]]
NULL
If there are no names then you need to index by a numeric:
> x[1][[ 1 ]] <- 1
[1] 1
It would seem more logical to have a list though than an array:
> y <- vector(mode = "list", length = 10)
> y
[[1]]
NULL
[[2]]
NULL
[[3]]
NULL
[[4]]
NULL
[[5]]
NULL
....

Resources