Trivial subset selection with array in R - arrays

I have an 6*3*3 dimensional array:
a<-array(data=rep(1:5,10),dim=c(6,3,3)
I have another vector with 3 numbers:
b<-1:3
I would like to do the following selection:
Select from the first column of a those values that that have b in their second column.
I would like to use b as an index for the third dimension of a. i.e. the first value of b should be searched in a[,,1] the second value of b in a[,,2] and the third value in a[,,3]
The original array looks like this:
a
, , 1
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 3 4
[3,] 3 4 5
[4,] 4 5 1
[5,] 5 1 2
[6,] 1 2 3
, , 2
[,1] [,2] [,3]
[1,] 4 5 1
[2,] 5 1 2
[3,] 1 2 3
[4,] 2 3 4
[5,] 3 4 5
[6,] 4 5 1
, , 3
[,1] [,2] [,3]
[1,] 2 3 4
[2,] 3 4 5
[3,] 4 5 1
[4,] 5 1 2
[5,] 1 2 3
[6,] 2 3 4
after the selection this is what I would like to get:
, , 1
[,1]
[5,] 5
, , 2
[,1]
[3,] 1
, , 3
[,1]
[1,] 2
[6,] 2

You can do:
lapply(seq_along(b), function(i) a[a[, 2, i] == b[i], 1, i, drop = FALSE])
Note that the output is a list of one-column matrices. I don't think you can get away without a list because the number of matches for each b[i] may differ. Also, you might want to remove drop = FALSE so the output will just be a list of vectors.

Related

Identifying dimension-specific index position in R using arr.ind

I understand that by setting ind.arr = TRUE, R will treat the array as an array or matrix instead of a single vector. However, I am having trouble extracting elements from a multi-dimensional array.
Creating a 3x2x3 array
qux <- array (data = c(10, 5, 1, 4, 7, 4, 3, 3, 1, 3, 4, 3, 1, 7, 8, 3, 7, 3), dim=c(3,2,3))
Output
> qux
, , 1
[,1] [,2]
[1,] 10 4
[2,] 5 7
[3,] 1 4
, , 2
[,1] [,2]
[1,] 3 3
[2,] 3 4
[3,] 1 3
, , 3
[,1] [,2]
[1,] 1 3
[2,] 7 7
[3,] 8 3
I would like to identify the dimension-specific index positions of elements that are either 3 OR 4. I tried to test it out by extracting elements that are 3 first and I got this as my output:
Extracting elements = 3
which ((qux ==3), arr.ind=T)
Output
> which ((qux ==3), arr.ind=T)
dim1 dim2 dim3
[1,] 1 1 2
[2,] 2 1 2
[3,] 1 2 2
[4,] 3 2 2
[5,] 1 2 3
[6,] 3 2 3
I'm not sure if what I'm doing is correct. May I know how do I get the exact position (row, column and dimension if possible) of elements that are either 3/4?
Edit
I got this as an output after using the code
which((qux ==3) | (qux==4), arr.ind=TRUE)
Output
dim1 dim2 dim3
[1,] 1 2 1
[2,] 3 2 1
[3,] 1 1 2
[4,] 2 1 2
[5,] 1 2 2
[6,] 2 2 2
[7,] 3 2 2
[8,] 1 2 3
[9,] 3 2 3
However, I do not understand what does all the 1s, 2s and 3s represent. Can someone explain it to me? Thank you.

R: extract matrix from array, using a matrix of indices

I´m coding in R and I have a 3 dimensional array that contains data (ab in the example). Then I have a matrix that contains indices of the 3rd array dimension (idx). This matrix has the same number of rows and columns of the array. I want to use the indices contained in idx to extract data from the array, to get a matrix with same dimension of idx. Please see the example below:
a <- c(1:9)
b <- rev(a)
#array of data
ab <- array(c(a,b), dim = c(3,3,2))
ab
, , 1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
, , 2
[,1] [,2] [,3]
[1,] 9 6 3
[2,] 8 5 2
[3,] 7 4 1
#matrix of indices
idx <- matrix(sample(1:2,9,replace=TRUE), nrow = 3)
idx
[,1] [,2] [,3]
[1,] 2 2 2
[2,] 2 1 1
[3,] 1 1 1
#now I want to get the following matrix:
[,1] [,2] [,3]
[1,] 9 6 3
[2,] 8 5 8
[3,] 3 6 9
#these two don´t do the job
ab[idx]
ab[ , ,idx]
Does anybody know how can I get that?
Many thanks!
Sara
We need an index for row/column and the third dimension (from 'idx') to extract the elements. We do this by cbinding the row index, column index with the 'idx'.
i1 <- dim(ab)[1]
j1 <- dim(ab)[2]
matrix(ab[cbind(rep(seq_len(i1), j1),rep(seq_len(j1), each = i1), c(idx))], ncol=3)
# [,1] [,2] [,3]
#[1,] 9 6 3
#[2,] 8 5 8
#[3,] 3 6 9
Might be a bit complicated, but it works at least:
First of all my idx:
[,1] [,2] [,3]
[1,] 2 2 1
[2,] 1 2 1
[3,] 2 2 2
First I made it both to a vector:
idVec <- as.vector(idx)
d3mat <- apply(ab,3,as.vector)
Then I constructed a vector, to run over each element:
len <- length(idVec)
len <- 1:len
Then I apllied a function to each element of the vector len:
resultvec <- sapply(len, function(x, vec, mat){return(mat[x,vec[x]])}, mat=d3mat, vec=idVec)
And then transform the result back to a matrix:
matrix(resultVec,3,3)
[,1] [,2] [,3]
[1,] 9 6 7
[2,] 2 5 8
[3,] 7 4 1

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)
}

Excluding specific row elements from row-wise function evaluation for 3D array [r]

I would like to apply a custom function to each row of a 3d array, excluding a specific value stored in the vector nul. For the ith row of the array (either layer), I would like to exclude from evaluation all values in that row matching ith value in the vector nul.
mat <- rep(cbind(c(1,3,0,1,4),c(0,4,1,2,1), c(2,3,0,4,0), c(1,0,4,2,0), c(0,2,3,0,1)),2)
arr <- array(mat, dim=c(5,5,2))
nul <- c(1,3,5,8,4)
I have tried many different things, but the closest I have come is:
x1 <- apply(arr,c(1,3), function(x)myfun(x[x!=(nul)]))
However, this results in the exclusion of row elements in arr which match corresponding row elements in nul for each row in nul.
"myfun" is a summation for sake of simplicity, though in reality this will be something more complicated:
> nul
[1] 1 3 5 8 4
> arr
, , 1
[,1] [,2] [,3] [,4] [,5]
[1,] 1 0 2 1 0
[2,] 3 4 3 0 2
[3,] 0 1 0 4 3
[4,] 1 2 4 2 0
[5,] 4 1 0 0 1
, , 2
[,1] [,2] [,3] [,4] [,5]
[1,] 1 0 2 1 0
[2,] 3 4 3 0 2
[3,] 0 1 0 4 3
[4,] 1 2 4 2 0
[5,] 4 1 0 0 1
> x1
[,1] [,2]
[1,] 3 3
[2,] 12 12
[3,] 8 8
[4,] 8 8
[5,] 6 6
As you can see, only the "1" at position [1,1,1] is excluded, instead of each matching value in that row. In addition, the function excludes "1" in each row, instead of just the first.
The desired output is:
[1,] 2 2
[2,] 6 6
[3,] 8 8
[4,] 8 8
[5,] 2 2
try to use the which function instead
res <- cbind(rep(0,5), rep(0,5)) #is the result matrix
count <- 1 #is the dimension count of the array
while (count <= dim(arr)[3]){
for (i in 1:nrow(arr[,,count])){
res[i,count] <- sum(arr[i,c(which(arr[i,,count] != nul[i])), count])
}
count <- count + 1
}
However i don't understand the ultimate output part.

Resources