Matlab populate a 3 dimensional array. - arrays

I'm quite new to Matlab and am trying to populate a 3 dimensional array. Basically I have 4 lots of 1x81 matrix that I want in one single 4x1x81 matrix. I tried to do this using a for loop to splice each 1x81 into a 4x1x81 but so far haven't had any luck. I'm sure there is a simpler way but need a fresh pair of eyes. Any help would be greatly appreciated, thanks!

I will give you an example and then you apply the same technique. You have to use the colon or : operator to achieve this task.
a=1;b=2;c=3;
Then a 3-D matrix can be formed as:
new3D_Mat(:,:,1)=a;
new3D_Mat(:,:,2)=b;
new3D_Mat(:,:,3)=c;
Output:
>> new3D_Mat
new3D_Mat(:,:,1) =
1
new3D_Mat(:,:,2) =
2
new3D_Mat(:,:,3) =
3

What exactly did you try? How about matrix(1,1,:)=myvector;matrix(2,1,:)=anotherone; or a loop in which you replace the first index with the loop variable? Consider
>> m(1,1,:)=rand(1,3)
m =
(:,:,1) =
0.3478
(:,:,2) =
0.0276
(:,:,3) =
0.5313
Out of curiosity, what is wrong with a 4x81 matrix? (If you already have one, permute may help you get a 4x1x81 3d array.)

Why use a 4x1x81 matrix?
Look at how easy it is to create a 4x81 matrix from four 1x81 matrices.
% Matrix of all ones
a = ones(1, 81);
% Matrix of all twos
b = ones(1, 81);
b = b .*2;
% Matrix of all threes
c = ones(1, 81); c = c .*3;
% Matrix of all fours
d = ones(1, 81); d = d .*4;
% Aggregate
all_of_em = [a; b; c; d];
Run whos to see your variables.
Name Size Bytes Class Attributes
a 1x81 648 double
all_of_em 4x81 2592 double
b 1x81 648 double
c 1x81 648 double
d 1x81 648 double

Related

Sub-setting symmetric matrices along the diagonal

I have an 8x8 matrix, e.g. A=rand(8,8). What I need to do is subset all 2x2 matrices along the diagonal. That means that I need to save matrices A(1:2,1:2), A(3:4,3:4), A(5:6,5:6), A(7:8,7:8). To better explain myself, the current version that I am using is the following:
AA = rand(8,8);
BB = zeros(8,2);
for i = 1:4
BB(2*i-1:2*i,:) = AA(2*i-1:2*i,2*i-1:2*i);
end
This works fine for small AA matrices and small AA submatrices, however as the size grows significantly (it can get up to even 50,000x50,000) using a for loop like the one above in not viable. Is there a way to achieve the above without the loop? I've thought of other approaches that could perhaps utilize upper and lower triangular matrices, however even these seem to need a loop at some point. Any help is appreciated!!
Here's a way:
AA = rand(8,8); % example matrix. Assumed square
n = 2; % submatrix size. Assumed to divide the size of A
mask = repelem(logical(eye(size(AA,1)/n)), n, n);
BB = reshape(permute(reshape(AA(mask), n, n, []), [1 3 2]), [], n);
This generates a logical mask that selects the required elements, and then rearranges them as desired using reshape and permute.
Here is an alternative that doesn't generate a full matrix to select the block diagonals, as in Luis Mendo' answer but instead directly generates the indices to these elements. It is likely that this will be faster for very large matrices, as creating the indexing matrix will be expensive in that case.
AA = rand(8,8); % example matrix. Assumed square
n = 2; % submatrix size. Assumed to divide the size of A
m=size(AA,1);
bi = (1:n)+(0:m:n*m-1).'; % indices for elements of one block
bi = bi(:); % turn into column vector
di = 1:n*(m+1):m*m; % indices for first element of each block
BB = AA(di+bi-1); % extract the relevant elements
BB = reshape(BB,n,[]).' % put these elements in the desired order
Benchmark
AA = rand(5000); % couldn't do 50000x50000 because that's too large!
n = 2;
BB1 = method1(AA,n);
BB2 = method2(AA,n);
BB3 = method3(AA,n);
assert(isequal(BB1,BB2))
assert(isequal(BB1,BB3))
timeit(#()method1(AA,n))
timeit(#()method2(AA,n))
timeit(#()method3(AA,n))
% OP's loop
function BB = method1(AA,n)
m = size(AA,1);
BB = zeros(m,n);
for i = 1:m/n
BB(n*(i-1)+1:n*i,:) = AA(n*(i-1)+1:n*i,n*(i-1)+1:n*i);
end
end
% Luis' mask matrix
function BB = method2(AA,n)
mask = repelem(logical(eye(size(AA,1)/n)), n, n);
BB = reshape(permute(reshape(AA(mask), n, n, []), [1 3 2]), [], n);
end
% Cris' indices
function BB = method3(AA,n)
m = size(AA,1);
bi = (1:n)+(0:m:n*m-1).';
bi = bi(:);
di = 0:n*(m+1):m*m-1;
BB = reshape(AA(di+bi),n,[]).';
end
On my computer, with MATLAB R2017a I get:
method1 (OP's loop): 0.0034 s
method2 (Luis' mask matrix): 0.0599 s
method3 (Cris' indices): 1.5617e-04 s
Note how, for a 5000x5000 array, the method in this answer is ~20x faster than a loop, whereas the loop is ~20 faster than Luis' solution.
For smaller matrices things are slightly different, Luis' method is almost twice as fast as the loop code for a 50x50 matrix (though this method still beats it by ~3x).

Combine 2D matrices to form 3D one in Matlab

I have 3 20x2 double arrays A, B and C. I want to combine them in one 3d array D so that D(:,:,1) will return A, D(:,:,2) will return B and D(:,:,3) will return C.
Using cat to concatenate along the third dimension might be the elegant way -
D = cat(3,A,B,C)
Here, the first input argument 3 specifies the dimension along which the concatenation is to be performed.
Like this?
A = 1*ones(20,2);
B = 2*ones(20,2);
C = 3*ones(20,2);
D = zeros(20,2,3); % Preallocate the D Matrix
D(:,:,1) = A;
D(:,:,2) = B;
D(:,:,3) = C;
D(1,1,1) % prints 1
D(1,1,2) % prints 2
D(1,1,3) % prints 3

How do I find the indices of a given array A1, *any* of whose values are practically equivalent to *any* of the values of a second array A2?

By "practically equivalent", I mean that their distances are of order epsilon apart (or 0.000001). Equality in MATLAB often doesn't really work for long floating numbers.
If I simply do abs(A1 - A2) < 0.000001, it's not going to work since size(A1) != size(A2)
You can get the answer by calculating distance between two vectors using MATLAB's pdist2 function.
dist=pdist2(A1,A2);
minDist=min(dist,[],2);
indices_A1=minDist<=0.000001;
desired_A1=A1(indices_A1);
Not tested, but should work.
Since you care about a distance from any element to any element, you can create a distance matrix from the vectorized matrices and probe that for the distance threshold. Example:
A = rand(10, 4); % (example) matrix A
B = rand(3, 5); % matrix B of different size
minDist = 0.005;
Solution: Repeat vectorized matrices, column- and row-wise to get same size matrices and apply matrix-based distance estimation:
Da = repmat(A(:), 1, length(B(:))); % size 40 x 15
Db = repmat(B(:)', length(A(:)), 1); % size 40 x 15
DD = Da - Db;
indA = any(abs(DD) < minDist, 2);
The use of any() will give you logical indices to any value of A that is close to any value of B). You can directly index/return the elements of A using indA.
The matrix DD (as #Shai also points out) can be equivalently estimated through bsxfun
DD = bsxfun(#minus, A(:), B(:)');
In addition: you can map from row-index (corresponding to A elements) back to matrix A indices using:
[iA, jA] = ind2sub(size(A), indA);
Assert/test that all the returned values are less than minDist,e.g. using:
for k = 1:length(iA);
d(k) = min(min(abs(A(iA(k), jA(k)) - B)));
end
all(d < minDist)
(tested in Octave 3.6.2)

Values of Variables Matrix NumPy

I'm working on a program that determines if lines intersect. I'm using matrices to do this. I understand all the math concepts, but I'm new to Python and NumPy.
I want to add my slope variables and yint variables to a new matrix. They are all floats. I can't seem to figure out the correct format for entering them. Here's an example:
import numpy as np
x = 2
y = 5
w = 9
z = 12
I understand that if I were to just be entering the raw numbers, it would look something like this:
matr = np.matrix('2 5; 9 12')
My goal, though, is to enter the variable names instead of the ints.
You can do:
M = np.matrix([[x, y], [w, z]])
# or
A = np.array([[x, y], [w, z]])
I included the array as well because I would suggest using arrays instead of of matrices. Though matrices seem like a good idea at first (or at least they did for me), imo you'll avoid a lot of headache by using arrays. Here's a comparison of the two that will help you decide which is right for you.
The only disadvantage of arrays that I can think of is that matrix multiply operations are not as pretty:
# With an array the matrix multiply like this
matrix_product = array.dot(vector)
# With a matrix it look like this
matrix_product = matrix * vector
Can you just format the string like this?:
import numpy as np
x = 2
y = 5
w = 9
z = 12
matr = np.matrix('%s %s; %s %s' % (x, y, w, z))

store data in array from loop in matlab

I want to store data coming from for-loops in an array. How can I do that?
sample output:
for x=1:100
for y=1:100
Diff(x,y) = B(x,y)-C(x,y);
if (Diff(x,y) ~= 0)
% I want to store these values of coordinates in array
% and find x-max,x-min,y-max,y-min
fprintf('(%d,%d)\n',x,y);
end
end
end
Can anybody please tell me how can i do that. Thanks
Marry
So you want lists of the x and y (or row and column) coordinates at which B and C are different. I assume B and C are matrices. First, you should vectorize your code to get rid of the loops, and second, use the find() function:
Diff = B - C; % vectorized, loops over indices automatically
[list_x, list_y] = find(Diff~=0);
% finds the row and column indices at which Diff~=0 is true
Or, even shorter,
[list_x, list_y] = find(B~=C);
Remember that the first index in matlab is the row of the matrix, and the second index is the column; if you tried to visualize your matrices B or C or Diff by using imagesc, say, what you're calling the X coordinate would actually be displayed in the vertical direction, and what you're calling the Y coordinate would be displayed in the horizontal direction. To be a little more clear, you could say instead
[list_rows, list_cols] = find(B~=C);
To then find the maximum and minimum, use
maxrow = max(list_rows);
minrow = min(list_rows);
and likewise for list_cols.
If B(x,y) and C(x,y) are functions that accept matrix input, then instead of the double-for loop you can do
[x,y] = meshgrid(1:100);
Diff = B(x,y)-C(x,y);
mins = min(Diff);
maxs = max(Diff);
min_x = mins(1); min_y = mins(2);
max_x = maxs(1); max_y = maxs(2);
If B and C are just matrices holding data, then you can do
Diff = B-C;
But really, I need more detail before I can answer this completely.
So: are B and C functions, matrices? You want to find min_x, max_x, but in the example you give that's just 1 and 100, respectively, so...what do you mean?

Resources