Reputation: 2606
Suppose I have a 4 dimensional n x n x n x n array A. A is a distance matrix, such that A[i,j,l,k] is the distance from location i,j to location pair l,k. Suppose I have an nxn matrix of location types T, lets say the types can be 0, 1, or 2, so T[i,j]=2 means the i,jth location is type 2. What is the easiest way to extract all the [i,j,l,k] entries of A such that T[i,j]=2 and T[l,k]=1, meaning the distances of all paths from a type 1 location to a type 2 location.
My thought was to use something like
type.0 = which(T == 0, arr.ind=T)
type.1 = which(T == 1, arr.ind=T)
type.2 = which(T == 2, arr.ind=T)
But the problem is that because A is four dimensional, the way R does its indexing its not like you can just do A[type.0,type.1]. Of course I could do it with loops, but is there a better way of doing it.
I couldn't find a past answer on here, but its possible I missed something.
Here is a simple test case with two types 0 and 1, a 2x2 lattice of locations (1,1), type 0 (1,2), type 0, (2,1), type 1, and (2,2) type 1.
A = array(c(0,1,1,1.4,1,0,1.4,1,1,1.4,0,1,1.4,1,1,0), dim = c(2, 2, 2, 2))
T = matrix(c(0,1,0,1),2,2)
I want all the distances from a type 0 cell to a type 1 cell
Upvotes: 0
Views: 798
Reputation: 2606
My guess is that there is a more elegant way of doing this. Its inspired by DWin's solution but takes care of all potential combinations of getting from a type 0 to a type 1 cell. Let me know if you guys think of a better way
> type
[,1] [,2] [,3]
[1,] 0 0 1
[2,] 0 1 0
type.0 = which(type == 0, arr.ind=T) #locations of type 0 cells
type.1 = which(type == 1, arr.ind=T) #locations of type 1 cells
nlocs0 = length(type.0[,1]) #number of locations of type 0
nlocs1 = length(type.1[,1]) #number of locations of type 1
reploc0 = rbind( do.call(rbind, rep(list(type.0), nlocs1)) ) #rbinded on top of itself nloc1 times
reploc1 = rbind( do.call(rbind, rep(list(type.1[1,]), nlocs0)) ) #rbinding the first location of type.1 on top of itself nlocs0 times
if(nlocs1>1){
for(i in 2:nlocs1){
reploc1 = rbind( rbind( do.call(rbind, rep(list(type.1[i,]), nlocs0)) ), reploc1)
}
}
d0_1 = A[cbind(reploc0,reploc1)]
Upvotes: 1
Reputation: 263411
I guess you have changed the request from the one stated in the first paragraph. See if this answers the second version.
A [ cbind( which(T == 0, arr.ind=TRUE), which(T == 1, arr.ind=TRUE) )]
#[1] 1 1
(At first I thought you might need abind but cbind works fine.)
Upvotes: 1