Reputation: 35
I am trying to reduce a multidimensional matrix with a vector.
Lets say the matrix A is 1000 x 10 x 100. The vector b could be 100 x 1 where the 100 entries are part of the first dimension of A. There is always exactly one element in a slice of the first dimension of A that matches each element of b.
How can i reduce the Matrix to the matching vector?
I tried
Ared= A[b,:,:]
but it doesn't work.
The new Matrix in this example should have the form 100 x 10 x 100
Does anyone have any ideas?
Upvotes: 2
Views: 1688
Reputation: 22255
Your logic is fine and would work if b was a vector. The reason it doesn't is that you're probably trying to index using a 2-dimensional array (i.e. rank 2) which simply happens to only have one column, rather than a vector (i.e. rank 1) array. I.e. I'm sure if you do size(b)
the result will be (2,1)
rather than (2,)
which is what it should have been.
If you obtain the corresponding vector for b, (e.g. collect(b)
) your indexing operation should work fine.
Example:
julia> A = rand(Int64[1,10],3,4,2)
3x4x2 Array{Int64,3}:
[:, :, 1] =
10 10 1 10
10 10 10 10
1 10 10 1
[:, :, 2] =
1 10 10 1
1 10 1 1
1 1 10 10
julia> b = [1; 3] # this will work. NOTE THE RESULTING TYPE!
2-element Array{Int64,1}:
1
3
julia> A[b,:,:]
2x4x2 Array{Int64,3}:
[:, :, 1] =
10 10 1 10
1 10 10 1
[:, :, 2] =
1 10 10 1
1 1 10 10
julia> c = [1 3]' # this will not. NOTE THE RESULTING TYPE
2x1 Array{Int64,2}:
1
3
julia> A[c,:,:]
ERROR: MethodError: `index_shape_dim` has no method matching index_shape_dim(::Array{Int64,3}, ::Int64, ::Array{Int64,2}, ::Colon, ::Colon)
julia> A[collect(c),:,:] # this will work again, c is now a vector
2x4x2 Array{Int64,3}:
[:, :, 1] =
10 10 1 10
1 10 10 1
[:, :, 2] =
1 10 10 1
1 1 10 10
Upvotes: 0
Reputation: 10990
Ok, I think I see what you're asking. You're looking for the findin()
function. It takes two arguments, each of which is a collection. It finds the elements of the first collection that are in the second, and returns the indices of those. Thus, we can apply this function to a slice from the first dimension of your array. Below are examples, starting in 2D, for simplicity, and then generalizing to 3D, which really is basically the same.
Note that it is necessary to select specific indices along the second and third dimensions (here I chose 1 for each), since otherwise, there is no definite element in the first dimension slice to compare to the contents of b
. (each dimension simply supplying one part of, in this case, a set of 3 numbers which together identify a specific place within the 3D array).
b = rand(100);
using Distributions
indices = sample(1:1000, 100, replace=false) ## random indices for where the elements in a slice of the first dimension of A will match those in b.
## 2D example
A = rand(1000,100);
A[indices,1] = b; ## set 100 random rows of A will now have their first element match one element of b
Ared = A[findin(A[:,1], b),:] ## find the rows in A where the first element is in B. Return the full values of those rows.
## 3D example
A3 = rand(1000,10,100);
A3[indices,1,1] = b;
Ared3 = A3[findin(A[:,1,1], b),:,:];
julia> size(Ared3)
(100,10,100)
Upvotes: 1