Guidance Needed For MATLAB MATRIX - matlab

I am working on a script which takes in array values and generates a matrix as shown in the code. What I want to do, based on below code, is that I want to search another matrix of given values and find the values corresponding to the cel and flr variables as defined in the program and make a new row to the matrix.
This is the current output:
C =
63.6944 51.7205 -38.2795 -39.0000 -38.0000 B value correspond to -39
107.5034 68.4665 -21.5335 -22.0000 -21.0000 B value correspond to -22
155.1031 75.2618 -14.7382 -15.0000 -14.0000 B value correspond to -15
203.8553 78.8393 -11.1607 -12.0000 -11.0000
253.0948 81.0307 -8.9693 -9.0000 -8.0000
302.5838 82.5070 -7.4930 -8.0000 -7.0000
352.2172 83.5677 -6.4323 -7.0000 -6.0000
401.9415 84.3662 -5.6338 -6.0000 -5.0000
to above I want to add another column which is searching corresponding values in given matrix say -39, -22, -15, 12, -9, -8, -7, -6 will be searched in a 2D matrix say B which is below. Now I want another column in below matrix which shows corresponding values of the matrix B in A.
B = [-39 14
-38 12
-15 10
-12 17
-9 45
-8 16]
a = 1;
for X = [50 100 150 200 250 300 350 400]
R = hypot(41.4586-2, X);
theta = atand(X/(41.4586-2));
dep = theta-90;
flr = floor(dep);
Y(row1:col1) = find(Y==flr);
dB1 = Y(row1:2);
cel = ceil(dep);
Y(row2,col2) = find(Y==cel);
dB2= Y(row2:2);
A(1,a) = R;
A(2,a) = theta;
A(3,a) = dep;
A(4,a) = flr;
A(5,a) = cel;
A(6,a) = dB1;
a = a+1;
end
C = transpose(A);

C =
63.6944 51.7205 -38.2795 -39.0000 -38.0000 14-> value of B in col 2
107.5034 68.4665 -21.5335 -22.0000 -21.0000 12
155.1031 75.2618 -14.7382 -15.0000 -14.0000 10
203.8553 78.8393 -11.1607 -12.0000 -11.0000 17
253.0948 81.0307 -8.9693 -9.0000 -8.0000 45
302.5838 82.5070 -7.4930 -8.0000 -7.0000 16
this should be the output

Related

Generate cell with random pairs without repetitions

How to generate a sequence of random pairs without repeating pairs?
The following code already generates the pairs, but does not avoid repetitions:
for k=1:8
Comb=[randi([-15,15]) ; randi([-15,15])];
T{1,k}=Comb;
end
When running I got:
T= [-3;10] [5;2] [1;-5] [10;9] [-4;-9] [-5;-9] [3;1] [-3;10]
The pair [-3,10] is repeated, which cannot happen.
PS : The entries can be positive or negative.
Is there any built in function for this? Any sugestion to solve this?
If you have the Statistics Toolbox, you can use randsample to sample 8 numbers from 1 to 31^2 (where 31 is the population size), without replacement, and then "unpack" each obtained number into the two components of a pair:
s = -15:15; % population
M = 8; % desired number of samples
N = numel(s); % population size
y = randsample(N^2, M); % sample without replacement
result = s([ceil(y/N) mod(y-1, N)+1]); % unpack pair and index into population
Example run:
result =
14 1
-5 7
13 -8
15 4
-6 -7
-6 15
2 3
9 6
You can use ind2sub:
n = 15;
m = 8;
[x y]=ind2sub([n n],randperm(n*n,m));
Two possibilities:
1.
M = nchoosek(1:15, 2);
T = datasample(M, 8, 'replace', false);
2.
T = zeros(8,2);
k = 1;
while (k <= 8)
t = randi(15, [1,2]);
b1 = (T(:,1) == t(1));
b2 = (T(:,2) == t(2));
if ~any(b1 & b2)
T(k,:) = t;
k = k + 1;
end
end
The first method is probably faster but takes up more memory and may not be practicable for very large numbers (ex: if instead of 15, the max was 50000), in which case you have to go with 2.

How to normalise each corresponding column in several matrices to values between -1 and 1 in Matlab?

I have several matrices, each with the same number of columns but with varying row sizes. Each matrix contains both positive and negative values. For grouping sake (because there are lots of matrices), each matrix is stored in a 2D cell array. A small example:
Matrix1:
C1 C2 C3
Val1 6 7 1
Val2 3 9 -7
Val3 -12 -22 -4
Matrix2:
C1 C2 C3
Val1 5 19 -2
Val2 4 21 9
Val3 -1 3 11
Val4 -30 13 7
Val5 3 -4 10
matrixStore{1,1} = Matrix1
matrixStore{1,2} = Matrix2
I am trying to normalise the values to a -1 to 1 range, in a column-wise, across-matrix manner.
So, using the example, I get max and min values for each column and put them in two vectors:
% C1: Max = 6, Min = -30
% C2: Max = 21, Min = -22
% C3: Max = 11, Min = -7
maxVals = [6, 21, 11];
minVals = [-30, -22, -7];
How do I now apply the max and min values to normalise each column for all matrices?
I use the following code to get the max and min values:
maxColsBuilder = [];
minColsBuilder = [];
% Find the max values for each column in every matrix and stack them together
maxColValsFromCell = cellfun(#max, matrixStore(1,:), 'Uni', 0);
maxColMatrix = cell2mat(maxColValsFromCell');
maxColsBuilder = [maxColsBuilder, maxColMatrix'];
% Do the same for the min values
minColValsFromCell = cellfun(#min, matrixStore(1,:), 'Uni', 0);
minColMatrix = cell2mat(minColValsFromCell');
minColsBuilder = [minColsBuilder, minColMatrix'];
% Find the max values for each column
maxVals = (max( maxColsBuilder, [], 2 ))'
% Also find the min values for column
minVals = (min( minColsBuilder, [], 2 ))'
Can anyone help me use these vectors to normalise my data as required, please?
Having done some extra searching, I found an answer by #rayryeng to this question (Min-max normalization of individual columns in a 2D matrix) that I modified to suit:
[unknown, matrices] = size(matrixStore);
for matrixIndex = 1:matrices
normMatrix = matrixStore{1, matrixIndex};
normMatrix = bsxfun(#minus, bsxfun(#rdivide, bsxfun(#minus, normMatrix, minVals), maxVals - minVals), 0.5) * 2
end;
This gives the same output as listed by #TomášKratochvíla in his answer.
When I apply both methods to some actual sample data, consisting of 6 matrices containing 12 columns and several thousand rows, I find the method using bsxfun to be quicker.
If anyone has any further info regarding either answer, please feel free to add comments.
The following code for each of your matrix from your matrixStore display the normalized version of the matrix:
[unknown, matrices] = size(matrixStore);
for matrixIndex = 1:matrices
[rows, columns] = size(matrixStore{1,matrixIndex});
normMatrix = matrixStore{1,matrixIndex};
for row = 1:rows;
for column = 1:columns;
normMatrix(row,column) = -1 + 2.*(matrixStore{1,matrixIndex}(row,column) - minVals(column))./(maxVals(column) - minVals(column));
end;
end;
normMatrix
end;
For the example you have provided:
normMatrix1 =
1.0000 0.3488 -0.1111
0.8333 0.4419 -1.0000
0 -1.0000 -0.6667
normMatrix2 =
0.9444 0.9070 -0.4444
0.8889 1.0000 0.7778
0.6111 0.1628 1.0000
-1.0000 0.6279 0.5556
0.8333 -0.1628 0.8889
If you have newer version of Matlab you can use normc function instead.

select a range of values from a matrix and swap them

I have a matrix and i want to select a range of elements.
for example i want to select all the elements that are lower than 182 and swap/change them.
does someone know an easy way or command to do this in matlab ?
thanx
Since you say "swap", I understand you mean a vector, not a matrix. You can do it as follows:
x = [ 1 34 66 22 200 55 301 ]; % data
[ values, ind ] = find(x<182);
x(ind) = x(ind(end:-1:1));
To simply replace them by another value such as NaN, do as follows. Note that this works also for matrices:
x = [ 1 34 66 22 200 55 301 ]; % data
x(x<182) = NaN;
Such things can usually be accomplished via logical indexing:
A = randn(1,100);
B = randn(size(A));
test = (A>1|A<0); % For example, values that are greater than 1 or less than 0
A(test) = B(test);
or another example:
A = randn(1,100);
test = (A>1|A<0);
A(test) = randn(1,nnz(test));
or another:
A = randn(1,100);
A(A>1|A<0) = NaN;
You may use loop like this:
for i = 1:length(matrix(:,1))
for j = 1:length(matrix(1,:))
if matrix(i,j) < 182
matrix(i,j) = NaN;
end
end
end

Matlab: Find values of a matrix between desired bounds

I have a matrix sorted in ascending order.
S = 25;
RT = zeros(S,2);
for i = 1:S;
for j = 1:i;
R = i *j;
T = R + j;
RT(j,:) = [R T];
end
end
sortRT = sortrows(RT, [1 2]);
disp(sortRT);
I want to find the sortRT elements which values is lower than 500 (for R) and 490 (for T) per column and place these values inside a matrix. Is it possible?
Just use find:
idx = find(sortRT(:,1)<500 & sortRT(:,2)<490)
idx' =
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
These are the rows where both R<500 and T<490. You can of course separate these two:
idxR500 = find(sortRT(:,1)<500);
idxT490 = find(sortRT(:,2)<490);
If you're just going to copy elements or rows, then find isn't even necessary and you can use logical indexing:
R500 = sortRT(find(sortRT(:,1)<500) , 1);
is the same as
R500 = sortRT(sortRT(:,1)<500 , 1);
This copies elements of the first column, if you want to copy the whole row, use the colon operator:
R500 = sortRT(sortRT(:,1)<500 , :);

A Fast and Efficient way to create a matrix from a series of product

Ax, Ay, Az: [N-by-N]
B=AA (a dyadic product)
It means :
B(i,j)= [Ax(i,j);Ay(i,j);Az(i,j)]*[Ax(i,j) Ay(i,j) Az(i,j)]
B(i,j) : a 3x3 matrix.
One way to construct B is:
N=2;
Ax=rand(N); Ay=rand(N); Az=rand(N); %# [N-by-N]
t=1;
F=zeros(3,3,N^2);
for i=1:N
for j=1:N
F(:,:,t)= [Ax(i,j);Ay(i,j);Az(i,j)]*[Ax(i,j) Ay(i,j) Az(i,j)];
t=t+1; %# t is just a counter
end
end
%# then we can write
B = mat2cell(F,3,3,ones(N^2,1));
B = reshape(B,N,N)';
B = cell2mat(B);
Is there a faster way for when N is large.
Edit:
Thanks for your answer. (It's faster)
Let's put:
N=2;
Ax=[1 2;3 4]; Ay=[5 6;7 8]; Az=[9 10;11 12];
B =
1 5 9 4 12 20
5 25 45 12 36 60
9 45 81 20 60 100
9 21 33 16 32 48
21 49 77 32 64 96
33 77 121 48 96 144
Run:
??? Error using ==> mtimes
Inner matrix dimensions must agree.
If I write :P = Ai*Aj; then
B =
7 19 31 15 43 71
23 67 111 31 91 151
39 115 191 47 139 231
10 22 34 22 50 78
34 78 122 46 106 166
58 134 210 70 162 254
That is defferent from above
A(:,:,1) deffer from [Ax(1,1) Ay(1,1) Az(1,1)]
Edit:
N=100;
Me :Elapsed time is 1.614244 seconds.
gnovice :Elapsed time is 0.056575 seconds.
N=200;
Me :Elapsed time is 6.044628 seconds.
gnovice :Elapsed time is 0.182455 seconds.
N=400;
Me :Elapsed time is 23.775540 seconds.
gnovice :Elapsed time is 0.756682 seconds.
Fast!
rwong: B was not the same.
Edit:
After some modification for my application :
by gnovice codes
1st code : 19.303310 seconds
2nd code: 23.128920 seconds
3rd code: 13.363585 seconds
It seems that any function calling like ceil,ind2sub ... make thw loops slow and shoud avoid if possible.
symIndex was interesting! Thank you.
Here's a fairly simple and general implementation that uses a single for loop to perform linear indexing and avoids dealing with 3-dimensional variables or reshaping:
%# General solution:
%# ----------------
B = cell(N);
for index = 1:N^2
A = [Ax(index) Ay(index) Az(index)];
B{index} = A(:)*A;
end
B = cell2mat(B);
EDIT #1:
In response to the additional question of how to reduce the number of calculations performed for a symmetric matrix B, you could use the following modified version of the above code:
%# Symmetric solution #1:
%# ---------------------
B = cell(N);
for index = find(tril(ones(N))).' %'# Loop over the lower triangular part of B
A = [Ax(index) Ay(index) Az(index)];
B{index} = A(:)*A;
symIndex = N*rem(index-1,N)+ceil(index/N); %# Find the linear index for the
%# symmetric element
if symIndex ~= index %# If we're not on the main diagonal
B{symIndex} = B{index}; %# then copy the symmetric element
end
end
B = cell2mat(B);
However, in such a case you may get better performance (or at least simpler looking code) by foregoing the linear indexing and using two for loops with subscripted indexing like so:
%# Symmetric solution #2:
%# ---------------------
B = cell(N);
for c = 1:N %# Loop over the columns
for r = c:N %# Loop over a subset of the rows
A = [Ax(r,c) Ay(r,c) Az(r,c)];
B{r,c} = A(:)*A;
if r ~= c %# If we're not on the main diagonal
B{c,r} = B{r,c}; %# then copy the symmetric element
end
end
end
B = cell2mat(B);
EDIT #2:
The second symmetric solution can be further sped up by moving the diagonal calculation outside of the inner loop (removing the need for a conditional statement) and overwriting A with the result A(:)*A so that we can update the symmetric cell entry B{c,r} using A instead of B{r,c} (i.e. updating one cell with the contents of another appears to carry some extra overhead):
%# Symmetric solution #3:
%# ---------------------
B = cell(N);
for c = 1:N %# Loop over the columns
A = [Ax(c,c) Ay(c,c) Az(c,c)];
B{c,c} = A(:)*A;
for r = c+1:N %# Loop over a subset of the rows
A = [Ax(r,c) Ay(r,c) Az(r,c)];
A = A(:)*A;
B{r,c} = A;
B{c,r} = A;
end
end
B = cell2mat(B);
And here are some timing results for the 3 symmetric solutions using the following sample symmetric matrices Ax, Ay, and Az:
N = 400;
Ax = tril(rand(N)); %# Lower triangular matrix
Ax = Ax+triu(Ax.',1); %'# Add transpose to fill upper triangle
Ay = tril(rand(N)); %# Lower triangular matrix
Ay = Ay+triu(Ay.',1); %'# Add transpose to fill upper triangle
Az = tril(rand(N)); %# Lower triangular matrix
Az = Az+triu(Az.',1); %'# Add transpose to fill upper triangle
%# Timing results:
%# --------------
%# Solution #1 = 0.779415 seconds
%# Solution #2 = 0.704830 seconds
%# Solution #3 = 0.325920 seconds
The big speed-up for solution 3 results primarily from updating the cell contents of B with the local variable A instead of updating one cell with the contents of another. In other words, copying cell contents with operations like B{c,r} = B{r,c}; carries more overhead than I expected.
A = cat(3, Ax, Ay, Az); % [N-by-N-by-3]
F = zeros(3, 3, N^2);
for i = 1:3,
for j = 1:3,
Ai = A(:,:,i);
Aj = A(:,:,j);
P = Ai(:) .* Aj(:);
F(i,j,:) = reshape(P, [1, 1, N^2]);
end
end
%# then we can write
B = mat2cell(F,3,3,ones(N^2,1));
B = reshape(B,N,N)';
B = cell2mat(B);