multi-dimension array manipulation R - arrays

I'm sorry but I can't find a way to replace every 0 in a 3-dimension array by the mean of the column they are in.
Thanks. So, for example, let's say I have this array j
j
, , 1
[,1] [,2]
[1,] 0 6
[2,] 1 5
[3,] 2 2
, , 2
[,1] [,2]
[1,] 11 0
[2,] 14 12
[3,] 0 14
, , 3
[,1] [,2]
[1,] 19 22
[2,] 20 23
[3,] 21 24
I would like
j
, , 1
[,1] [,2]
[1,] 1 6
[2,] 1 5
[3,] 2 2
, , 2
[,1] [,2]
[1,] 11 26/3
[2,] 14 12
[3,] 25/3 14
, , 3
[,1] [,2]
[1,] 19 22
[2,] 20 23
[3,] 21 24

You can use apply for this.
Starting with the following data :
arr <- array(0:5,dim=c(4,3,2))
, , 1
[,1] [,2] [,3]
[1,] 0 4 2
[2,] 1 5 3
[3,] 2 0 4
[4,] 3 1 5
, , 2
[,1] [,2] [,3]
[1,] 0 4 2
[2,] 1 5 3
[3,] 2 0 4
[4,] 3 1 5
You can do :
apply(arr, c(2,3),function(v) { v[v==0] <- mean(v); v})
Which gives :
, , 1
[,1] [,2] [,3]
[1,] 1.5 4.0 2
[2,] 1.0 5.0 3
[3,] 2.0 2.5 4
[4,] 3.0 1.0 5
, , 2
[,1] [,2] [,3]
[1,] 1.5 4.0 2
[2,] 1.0 5.0 3
[3,] 2.0 2.5 4
[4,] 3.0 1.0 5

Related

Reshape N 2-d matrices (T*M) into a 3d tensor of (T*N*M) with tidyverse/R

For each of my N variables, I have a (T * M) feature matrix, i.e., M observations per t \in T. The problem is how to convert this into a (T * N * M) array. For example, in the following example N=2, T=3, M=4 :
x1 <- matrix(1:24, 3,4)
> x1
[,1] [,2] [,3] [,4]
[1,] 1 4 7 10
[2,] 2 5 8 11
[3,] 3 6 9 12
x2 <- matrix(25:48, 3,4)
x2
[,1] [,2] [,3] [,4]
[1,] 25 28 31 34
[2,] 26 29 32 35
[3,] 27 30 33 36
And I need to make a 3 dimensional (number of rows) array, such that the first element is
[,1] [,2] [,3] [,4]
[1,] 1 4 7 10
[2,] 25 28 31 34
and the second is:
[,1] [,2] [,3] [,4]
[1,] 2 5 8 11
[2,] 26 29 32 35
and third:
[,1] [,2] [,3] [,4]
[1,] 3 6 9 12
[2,] 27 30 33 36
and so on and so forth. For the following example, the output's dimensions should be (3,2,4).
I need to do this for relatively large N and T, so appreciate extendable implementations!
Here is a base R option.
out <- `dim<-`(rbind(c(t(x1)), c(t(x2))), c(2, 4, 3))
out
#, , 1
#
# [,1] [,2] [,3] [,4]
#[1,] 1 4 7 10
#[2,] 25 28 31 34
#
#, , 2
#
# [,1] [,2] [,3] [,4]
#[1,] 2 5 8 11
#[2,] 26 29 32 35
#
#, , 3
#
# [,1] [,2] [,3] [,4]
#[1,] 3 6 9 12
#[2,] 27 30 33 36
When we call x <- rbind(c(t(x1)), c(t(x2))) we get the following matrix as a result
x
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
#[1,] 1 4 7 10 2 5 8 11 3 6 9 12
#[2,] 25 28 31 34 26 29 32 35 27 30 33 36
We need to change the dimensions of this object for which we can do
dim(x) <- c(2, 4, 3)
Another way to get the same result is to call the replacement method of dim in its functional form, i.e.
`dim<-`(...)
Which allows us to do all in one line.

R reshape matrix into multidimensional array to be used in convolutional neural network training

I'm terribly stuck at reshaping a matrix into multidimensional array to be used in convolutional neural network training.
Here's a sample 2x16 matrix (the actual matrix will be around 11000x1024)
two_samples <- structure(c(257, 17, 258, 18, 65795, 19, 65796, 20, 261, 21,
262, 22, 65799, 23, 65800, 24, 9, 25, 10, 26, 65547, 27, 65548,
28, 13, 29, 14, 30, 65551, 31, 65552, 32), .Dim = c(2L, 16L))
two_samples
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
#> [1,] 257 258 65795 65796 261 262 65799 65800 9 10 65547 65548
#> [2,] 17 18 19 20 21 22 23 24 25 26 27 28
#> [,13] [,14] [,15] [,16]
#> [1,] 13 14 65551 65552
#> [2,] 29 30 31 32
Here, each row is one sample and I would like to represent each sample as if it's color image. And I would like to arrange the data such that it can be used with Keras/Tensorflow for CNN training.
Generating RGB data from decimal numbers is done via bitwAnd() and bitwShiftR() functions. I run the commands below to generate RGB from the matrix. Afterwards I used dim() for array and aperm() to reshape the array:
mat_r <- bitwAnd(bitwShiftR(t(two_samples),16), 255)
mat_g <- bitwAnd(bitwShiftR(t(two_samples),8), 255)
mat_b <- bitwAnd(t(two_samples),255)
two_samples_flat <- array(c(mat_r, mat_g, mat_b))
arr <- array(two_samples_flat, dim=c(4,4,3,2))
data <- aperm(arr, c(4,1,2,3))
data[1,,,]
#> , , 1
#>
#> [,1] [,2] [,3] [,4]
#> [1,] 0 0 0 0
#> [2,] 0 0 0 0
#> [3,] 1 1 1 1
#> [4,] 1 1 1 1
#>
#> , , 2
#>
#> [,1] [,2] [,3] [,4]
#> [1,] 0 0 0 0
#> [2,] 0 0 0 0
#> [3,] 0 0 0 0
#> [4,] 0 0 0 0
#>
#> , , 3
#>
#> [,1] [,2] [,3] [,4]
#> [1,] 1 1 0 0
#> [2,] 1 1 0 0
#> [3,] 1 1 0 0
#> [4,] 1 1 0 0
However, bit functions return flat vectors and the modifying the dimension afterwards does not allow correct slicing of the multidimensional array. My expected dimension and output (one sample shown) are shown below
> dim(data)
2 4 4 3
> data[1,,,]
, , 1
[,1] [,2] [,3] [,4]
[1,] 0 0 1 1
[2,] 0 0 1 1
[3,] 0 0 1 1
[4,] 0 0 1 1
, , 2
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 1 1 1 1
[3,] 0 0 0 0
[4,] 0 0 0 0
, , 3
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
So, my question is, how can I prepare a multidimensional array from a matrix so that I can use with CNN. If I get this right, I can use array_reshape to reshape it to be used for dense layer network: array_reshape(data, c(num_of_samples, width*height*3))

Mean of multiple dimensions' observations within array

I have got an array as follows:
ar.1 = array(1:12, dim=c(2,2,3))
> ar.1
, , 1
[,1] [,2]
[1,] 1 3
[2,] 2 4
, , 2
[,1] [,2]
[1,] 5 7
[2,] 6 8
, , 3
[,1] [,2]
[1,] 9 11
[2,] 10 12
I just need to compute the mean between the values in the 3 different layers and obtain a 2-dimensional matrix.
Expected output:
5 7
6 8
5 = (1+5+9) / 3
6 = (2+6+10) / 3
etc..
It should be really easy but I couldn't find any quick solution yet as my real array is larger than 2x2x3.
Thanks
Try this
matrix(rowMeans(apply(ar.1, 3, c)), dim(ar.1)[1], dim(ar.1)[2])
# [,1] [,2]
#[1,] 5 7
#[2,] 6 8

Sum of matrices in 3-dimensional object of variable dimensions without looping

I have a 3-dimensional object in R, which contains n square matrices. For example:
myObject[,,1] # returns a square matrix
myObject[,,2] # returns a square matrix of the same size
...
All the matrices within the object are of the same size. I'd like to add all matrices together, without a loop. This is simple enough if I know how many matrices are in the object. For example:
matrixSum <- myObject[,,1] + myObject[,,2] + myObject[,,3]
The problem is, I need to do this for several thousand such objects, and there are a variable number of matrices in each object. Is there any way I can do this without a loop? In a sense, I'd like to try to "vectorize" this summation.
The most convient, but certainly not the fastest, is to use apply:
matrixSum <- apply(myObject, c(1,2), sum)
Example
myObject <- array(c(1,2,3),dim = c(3,4,3))
myObject
, , 1
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 2 2 2 2
[3,] 3 3 3 3
, , 2
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 2 2 2 2
[3,] 3 3 3 3
, , 3
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 2 2 2 2
[3,] 3 3 3 3
apply(myObject, c(1,2), sum)
[,1] [,2] [,3] [,4]
[1,] 3 3 3 3
[2,] 6 6 6 6
[3,] 9 9 9 9
Addition:
Using rowSums should be must faster:
rowSums(myObject, dims = 2)
[,1] [,2] [,3] [,4]
[1,] 3 3 3 3
[2,] 6 6 6 6
[3,] 9 9 9 9

count the number of values greater than each value in a column of an array in r

Say I had an array with x representing repeat measurements (1-4), y representing treatments (A,B) and z representing timepoints (1-3)
x <- c(2,2,4,15,17,13,3,10,3,4,11,14,1,3,19,6,13,6,12,18,9,13,12,16)
dim(x) <- c(4,2,3)
, , 1
[,1] [,2]
[1,] 2 17
[2,] 2 13
[3,] 4 3
[4,] 15 10
, , 2
[,1] [,2]
[1,] 3 1
[2,] 4 3
[3,] 11 19
[4,] 14 6
, , 3
[,1] [,2]
[1,] 13 9
[2,] 6 13
[3,] 12 12
[4,] 18 16
I want to create a new array that has the number of times each replicate is greater than all other replicates for that treatment and timepoint combination:
, , 1
[,1] [,2]
[1,] 2 0 #both 4 and 15 are bigger then 2, so for 1,1,1 the result is 2
[2,] 2 1
[3,] 1 3 #15 is the only replicate bigger than 4 so result for 3,1,1 is 1
[4,] 0 2
, , 2
[,1] [,2]
[1,] 3 3
[2,] 2 2
[3,] 1 0
[4,] 0 1
, , 3
[,1] [,2]
[1,] 1 3
[2,] 3 1
[3,] 2 2
[4,] 0 0
apply can do this, acting within each column (2) and strata (3):
## recreate your data array:
arr <- c(2,2,4,15,17,13,3,10,3,4,11,14,1,3,19,6,13,6,12,18,9,13,12,16)
dim(arr) <- c(4,2,3)
## one liner using apply
apply(arr, 2:3, function(x) sapply(x, function(y) sum(y < x) ) )
#, , 1
#
# [,1] [,2]
#[1,] 2 0
#[2,] 2 1
#[3,] 1 3
#[4,] 0 2
#
#, , 2
#
# [,1] [,2]
#[1,] 3 3
#[2,] 2 2
#[3,] 1 0
#[4,] 0 1
#
#, , 3
#
# [,1] [,2]
#[1,] 1 3
#[2,] 3 1
#[3,] 2 2
#[4,] 0 0
Here you go... If you're question is incorrectly phrased (as I suspect above), then you will need to use "<" instead of ">".
a <- array(rnorm(24), dim= c(4,2,3))
cnts <- function(a) {
a2 <- array(NA, dim= dim(a))
for (i in 1:dim(a)[3]) {
for (j in 1:dim(a)[2]) {
for (k in 1:length(a[,j,i])) {
a2[k,j,i] <- sum(a[k,j,i] > a[,j,i])
}
}
}
return(a2)
}

Resources