Finding the dimension indexes of elements of an array - arrays

Consider this array:
the.seq <- 1:4
sol<- outer(outer(the.seq, the.seq, `+`), the.seq, `+`)
I want to find all elements that sum 6. That is pretty easy to do with which:
indices <- which(sol == 6)
indices
[1] 4 7 10 13 19 22 25 34 37 49
Now I want a vector with the dimension indexes of these elements, the answer would be:
[,1] [,2] [,3]
[1,] 4 1 1
[2,] 3 2 1
[3,] 2 3 1
[4,] 1 4 1
[5,] 3 1 2
[6,] 2 2 2
[7,] 1 3 2
[8,] 2 1 3
[9,] 2 1 3
[10,] 1 1 4
How would you do this?

You can use the arr.ind argument in which. When set to TRUE, which will return the array indices for which its first argument is TRUE.
which(sol == 6, arr.ind = TRUE)
# dim1 dim2 dim3
# [1,] 4 1 1
# [2,] 3 2 1
# [3,] 2 3 1
# [4,] 1 4 1
# [5,] 3 1 2
# [6,] 2 2 2
# [7,] 1 3 2
# [8,] 2 1 3
# [9,] 1 2 3
#[10,] 1 1 4

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 Filling 3-dimensional array by row

I know there have been similar topics but they don't seem to answer my problem. I have a 3-dimensional array, composed of matrices (10,5).
I want to fill each matrix by row, by let say 1:5.
Previous topics talks about aperm, but here's the problem : since my matrices are not symmetric, when I first fill them by column as follows :
kappa=array(0,dim=c(10,5,2))
kappa[1:10,,1]=1:5
kappa[,,1]
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 1 1
[2,] 2 2 2 2 2
[3,] 3 3 3 3 3
[4,] 4 4 4 4 4
[5,] 5 5 5 5 5
[6,] 1 1 1 1 1
[7,] 2 2 2 2 2
[8,] 3 3 3 3 3
[9,] 4 4 4 4 4
[10,] 5 5 5 5 5
Since the column dimension is lower than the row dim, the sequence is replicated. So when I aperm the result, it gives :
aperm(kappa[,,1])
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 2 3 4 5 1 2 3 4 5
[2,] 1 2 3 4 5 1 2 3 4 5
[3,] 1 2 3 4 5 1 2 3 4 5
[4,] 1 2 3 4 5 1 2 3 4 5
[5,] 1 2 3 4 5 1 2 3 4 5
But what I want instead is
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
[2,] 1 2 3 4 5
[3,] 1 2 3 4 5
[4,] 1 2 3 4 5
[5,] 1 2 3 4 5
[6,] 1 2 3 4 5
[7,] 1 2 3 4 5
[8,] 1 2 3 4 5
[9,] 1 2 3 4 5
[10,] 1 2 3 4 5

Return the indices of a 3D array in R based on multiple values

I would like to obtain the indices of a 3D array in R (ie. arr[x,y,z]) based on multiple values. Specifically, using the first z dimension to subset values in the second z dimension. Here is a example:
# create example array
> m1 <- matrix(c(rep("a",5), rep("b",5), rep("c",5)), nr = 5)
> m2 <- matrix(c(rep(100, 5), rep(10, 5), rep(10, 5)), nr = 5)
> arr <- array(c(m1, m2), dim = c(dim(m1), 2))
#use which() to return the indices in m2 that correspond to indices with
#"a" and "c" values in m1. This does not work as expected.
> ac.ind <- which(arr[,,1] %in% c("a", "c"), arr.ind = T)
> ac.ind
[1] 1 2 3 4 5 11 12 13 14 15
which() returns an vector of positions in m1 that correspond to "a" and "c", not the matrix indices (the (x,y) positions). I would like ac.ind to return:
row col
[1,] 1 1
[2,] 2 1
[3,] 3 1
[4,] 4 1
[5,] 5 1
[1,] 1 3
[2,] 2 3
[3,] 3 3
[4,] 4 3
[5,] 5 3
If I do a more simple which() subset, it does return the indices:
#use which to return indices in m2 that correspond to only "a" in m1
>a.ind <- which(arr[,,1] == c("a"), arr.ind = T)
>a.ind
row col
[1,] 1 1
[2,] 2 1
[3,] 3 1
[4,] 4 1
[5,] 5 1
I am using %in% since I want to subset based on two values in m1 ("a" and "c" values). Is there a way to return the indices of an array based on two values in R?
The issue is that arr[,,1] %in% c("a", "c") returns a vector. One way is to cast this as a matrix with the number of rows equaling the first dimension of arr:
ac.ind <- which(matrix(arr[,,1] %in% c("a", "c"), nrow=dim(arr)[1]), arr.ind = T)
## row col
## [1,] 1 1
## [2,] 2 1
## [3,] 3 1
## [4,] 4 1
## [5,] 5 1
## [6,] 1 3
## [7,] 2 3
## [8,] 3 3
## [9,] 4 3
##[10,] 5 3
Something like this but it is not very efficient because it has to go twice through the data:
ac.ind <- which(arr[,,1] == "c" | arr[,,1] == "a" , arr.ind = T)
ac.ind
row col
[1,] 1 1
[2,] 2 1
[3,] 3 1
[4,] 4 1
[5,] 5 1
[6,] 1 3
[7,] 2 3
[8,] 3 3
[9,] 4 3
[10,] 5 3

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.

Trivial subset selection with array in R

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.

Resources