Suppose
t=c(0,0.5,0.7,0.9,1,1.2) and
v=matrix(1:40, nrow=5, ncol=8)
v
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 6 11 16 21 26 31 36
[2,] 2 7 12 17 22 27 32 37
[3,] 3 8 13 18 23 28 33 38
[4,] 4 9 14 19 24 29 34 39
[5,] 5 10 15 20 25 30 35 40
I would like to make an array of order 5x6x4.
array <- array(NA, dim = c(5, 6, 4))
5 is the number of rows, 6 is the length of t and 4 is the number of arrays. to create the first array, I would like to consider only the first two columns of v, and for each time point, the first element of the first matrix is filled by v[1,1]+v[1,2]*t[] which is the value of the first element of the first matrix of the first array which is the value of array[1,1,1]
, similarly, array[2,1,1]e v[2,1]+v[2,2]*t[1]
For the second array consider only 3rd and 4th column of v. For the third array consider only 5th and 6th column of v, and Finally, for the fourth array, consider the last two columns of v.
I would appreciate if anyone can help me using a for loop or alternative ways?
Thanks
Try these nested loops:
ary <- array(NA, dim = c(5, 6, 4))
for (i in 1:5) {
for (j in 1:6) {
for (k in 1:4) {
ary[i, j, k] <- v[i, k * 2 - 1] + v[i, k * 2] * t[j]
}
}
}
Related
I need to create a 3D array sorted by row, from left to right and descendent.
x <- 100
I have tried with this:
b <- array(1:96, dim= c(8,4,3))
but it sorts firstly descendently. Using apperm(b) doesn't work as well
The result I want is this:
, , 1
1 2 3 4 5
6 7 8 9 10
11 12 13 14
15 16 17 18
19 20 21 22
array by default fill values along 1st dimension, then 2nd dimension, then 3rd; What you are looking for is fill it in the order of (2nd, 1st, 3rd), you can initialize the array with the shape of 1st dimension and 2nd dimension switched and then use aperm on it:
b <- aperm(array(1:96, dim= c(4,8,3)), c(2,1,3))
# ^ ^ ^ ^ switch the dimension twice here
b
, , 1
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
Edit: My first try, but #Psidom's answer is the right way to do this.
You need to make it as a combination of 3 matrices and then combine them into an array. In the code below I used 96*i/3 to make it flexible for more than 3 matrices to be combined.
b <- array( c( aperm(array(1:(96*1/3), dim = c(4,8))),
aperm(array(33:(96*2/3), dim = c(4,8))),
aperm(array(65:(96*3/3), dim = c(4,8))) ) ,
dim = c(8, 4, 3))
This will be the output:
b[, , 1]
# [,1] [,2] [,3] [,4]
# [1,] 1 2 3 4
# [2,] 5 6 7 8
# [3,] 9 10 11 12
# [4,] 13 14 15 16
# [5,] 17 18 19 20
# [6,] 21 22 23 24
# [7,] 25 26 27 28
# [8,] 29 30 31 32
Lets assume I have an array of dim(x) <- c(3,3,3). I also have a df or matrix with two** columns containing index combinations that I need.
When I pass x[df[[1]],df[[2]],] I get a VERY large array which I then need to go through and take the diagonal of using the apply function. This is very memory and time inefficient. Is there some sort of shortcut (without using for loops) to index an array so that it would return the vector of values that the df asks for.
Trivial Example:
`a <- array(1:27,dim = c(3,3,3))
df <- data.frame(c(1,2,2,1,3,2),c(2,3,2,1,3,2))`
In this example, I would want to pass something like "a[df[[1]],df[[2]],]"
and get something like this (or transposed):
. [,1] [,2] [,3] [,4] [,5] [,6]
[1,] 4 8 5 1 9 5
[2,] 13 17 14 10 18 14
[3,] 22 26 23 19 27 23
When I pass that function now, I get a 3-d array of dim = c(6,6,3) as apposed to the more helpful dim = c(6,3). I can easily take apply(result, 3,diag) to get what I want, but when df>>6 it takes up a lot of space (like 750GB of space and throws warnings, errors and stops execution before beginning)
This works
temp <- array(1:27, dim=c(3,3,3))
df <- data.frame(a=c(1,2,3), b=c(1,2,3), c=c(1,2,3))
temp[cbind(df[[1]], df[[2]], df[[3]])]
[1] 1 14 27
This is sometimes referred to as matrix indexing.
To query by two of the dimensions and leave the third one open, you might just use the regular matrix subsetting: For example, to select the the first and second row and second column for each of the "z" dimension matrices, you could use something like temp[1:2, 2,] or from your dataset:
temp[1:2, 2,]
[,1] [,2] [,3]
[1,] 4 13 22
[2,] 5 14 23
temp[df[[1]][1:2], df[[2]][2], ]
[,1] [,2] [,3]
[1,] 4 13 22
[2,] 5 14 23
Which are of course identical.
I'm crafting a simulation model, and I think this problem has an easy fix, but I'm just not that used to working with arrays. Let's say I have an array, Array1, that has 3 dimensions. The first two are of constant and equal length, L, but the third dimension can be of length from 1 to X at any given time.
I want to be able to periodically subset Array1 to create a second array, Array2, that is composed of up to the last Y "sheets" of Array1. In other words, if the length of the third dimension of Array1 is greater than Y, then I want just the last Y sheets of Array1 but, if it's less than Y, I want all sheets of Array1.
I know that I can crudely pull this off using the tail function and a little finagling:
tmp1 = tail(Array1, (L*L*Y))
Array2 = array(tmp1, dim = (L, L, (L*L/length(tmp1))))
But it seems like there could be a more elegant way of doing this. Is there an equivalent of tail for arrays in R? Or is there a way that Array2 could be produced via simple logical indexing of Array1? Or perhaps the apply function could be used somehow?
Were you after something like this?
a <- array(1:(3*4*5), dim=c(3,4,5))
x <- dim(a)[3]
y <- 2
a[, , seq(to=x, len=min(x, y))]
, , 1
[,1] [,2] [,3] [,4]
[1,] 37 40 43 46
[2,] 38 41 44 47
[3,] 39 42 45 48
, , 2
[,1] [,2] [,3] [,4]
[1,] 49 52 55 58
[2,] 50 53 56 59
[3,] 51 54 57 60
In the 3 Dimensional array bellow :
ar <- array(someData, c(5, 5, 5));
rownames(ar) <- ...; #to set up row names
colnames(ar) <- ...; #to set up col names
How can i set the third dimension names ?
You can either set the dimnames argument when defining the array:
ar <- array(data = 1:27,
dim = c(3, 3, 3),
dimnames = list(c("a", "b", "c"),
c("d", "e", "f"),
c("g", "h", "i")))
and/or you can set the dimnames of the third dimension like so:
dimnames(ar)[[3]] <- c("G", "H", "I")
Still starting in R but I found this way that may be useful for large multidimensional array.
Instead of naming each of the indexes ('a','b','c','d',....), you can use provideDimnames() function to automatic generate the index names following the pattern you choose.
Creating data
ar <- array (data = 1:(4*3*2) , dim=c(4,3,2))
> ar
, , 1
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
, , 2
[,1] [,2] [,3]
[1,] 13 17 21
[2,] 14 18 22
[3,] 15 19 23
[4,] 16 20 24
Labelling dimensions
ar <- provideDimnames(ar , sep = "_", base = list('row','col','lev'))
And you get
> ar
, , lev
col col_1 col_2
row 1 5 9
row_1 2 6 10
row_2 3 7 11
row_3 4 8 12
, , lev_1
col col_1 col_2
row 13 17 21
row_1 14 18 22
row_2 15 19 23
row_3 16 20 24
Within R I would like to transform an array (dimensions: i, j, k) into a matrix such that the observations (i.e. rows) of the new matrix are each element from the array pulled k "layers" at a time. Essentially, again, the rows of the new matrix will be composed of each element of the previous array with the columns of the matrix being equivalent to the k dimension of the array. Thus, the new matrix should be composed of i*j rows with k columns.
Please let me know if I can clarify or provide an example of input / output!
Thanks!
Edit:
This code works (but is not optimized) —
m = array(1:27,dim = c(3,3,3))
m
dim = dim(m)
mparam = dim[3]
listm = list()
for (i in 1:mparam){
listm[[i]] = as.vector(m[,,i])
}
untran = do.call(rbind,listm)
transposed = t(untran)
transposed
Like this?
m <- array(1:27,dim = c(3,3,3))
> m
, , 1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
, , 2
[,1] [,2] [,3]
[1,] 10 13 16
[2,] 11 14 17
[3,] 12 15 18
, , 3
[,1] [,2] [,3]
[1,] 19 22 25
[2,] 20 23 26
[3,] 21 24 27
> matrix(m,9,3)
[,1] [,2] [,3]
[1,] 1 10 19
[2,] 2 11 20
[3,] 3 12 21
[4,] 4 13 22
[5,] 5 14 23
[6,] 6 15 24
[7,] 7 16 25
[8,] 8 17 26
[9,] 9 18 27