Considering the fact that i have gotten some clarity on this current question, I have edited the code to conform with my current problem with the code. So now the problem i have with my code is that it does not loop any more. if i place a for loop and some conditions, the value of groups which is supposed to change with every loop does not therefore causing an error at k is 2 in the loop. The initial value of groups is gotten from the first part of the code which gets its value form a different array, but the for loop part of the code is supposed to use that initial groupsvalue and then continue changing from there. that is where the problem comes, as the value of groups refuses to change.
A = connections;
% Engine
tic
[m, n] = size(A);
groups = [];
ng = 0;
k=1;
w= 1:2:3;
u = unique(A(k,w)); % representation of kth row
[in, J] = ismember(A(k:end,:),u);
l = m-k+1;
r = repmat((1:l).', n, 1);
c = accumarray([r(in) J(in)],1,[l n]); % count
c = bsxfun(#min,c,c(1,:)); % clip
rows = sum(c,2)==2; % check if 2 elements are common
if any(rows)
ng = +1;
groups = (k-1) + [1; find(rows)];
end
gr=groups(end);
nwrry= [A(k,:);A(gr,:)];
for k=1:5
h=[];
h(k)= groups(end);
dff= setdiff(nwrry(end,:),nwrry(end-1,:));
[rw,cl]= find(nwrry==dff);
if cl==3
w=1:2:cl;
else
if cl==2
w=1:cl;
else
w=cl:2;
end
end
u = unique(A(h(k),w)); % representation of kth row
[in, J] = ismember(A(k:end,:),u);
l = m-k+1;
r = repmat((1:l).', n, 1);
c = accumarray([r(in) J(in)],1,[l n]); % count
c = bsxfun(#min,c,c(1,:)); % clip
rows = sum(c,2)==2; % check if 2 elements are common
if any(rows)
ng = ng+1;
groups = (k-1) + [1; find(rows)];
end
nwrry = [nwrry;A(groups(end),:)]
k=k+1
end
connections is the 800 by 3 array. if you want to test it and see what it gives as a result please make sure the array has at most 2 values in a row common with another row.
I have been able to answer this question. Thank you all who have commented with your advices and help because i did look into what you all said and been able to come up with something worthwhile.
The complete code is below;
%% call connections
A= connections;
[m, n] = size(A);%% calculate number of rows (m) and columns(n) in A
%% find rows with similar values as row 1
[a, b]=find(A(1:end,:) == A(1,1));%% Find rows with similar value as the first value of row 1
[a1, b1]=find(A(1:end,:) == A(1,2));%% Find rows with similar value as the second value of row 1
[a2, b2]=find(A(1:end,:) == A(1,3));%% Find rows with similar value as the third value of row 1
%% find the rows with atleast 2 values similar to row 1
int1= intersect(a,a1);%% Find same row numbers between a and a1
int2= intersect(a,a2);%% Find same row numbers between a and a2
int3= intersect(a1,a2);%% Find same row numbers between a1 and a2
ints=[int1;int2;int3];%% Place all intersections in one array(ints)
%% delete row number that is same with row number 1
ints= unique(ints);%% delete repeated row numbers
[Lia,Locb] = ismember(ints(1:end,:),1);%% Find same row numbers same with row number 1
[z, x]=find(Lia(1:end,:) == 1);%% Find row numbers equal to 1 in Lia
ints(z(1:end),:)=[];%% delete row numbers that is same with row number 1
%% place the searched row number and the similar row number in an array(gr)
gr=1;%% Place initial row number(1) in one array(gr)
tg=[a;a1;a2];%% Place all row numbers with similar value as row 1 in one array(tg)
if isempty(ints)%% conditions when ints is empty
f= setdiff(tg,gr);%% Find row numbers in tg not present in gr
gr=[gr;f(1,:)];%% add the similar row number in array gr
else %% conditions when ints is NOT empty
gr=[gr;ints(end)]; %% add the similar row number in array gr
end
%% place the searched row and the similar row in an array(nwrry)
nwrry= [A(1,:);A(gr(end),:)];
%% Create loop for all rows in A and repeat all processes above
for i=1:m-2
hrry=[];
hrry(i)= gr(end);
[a, b]=find(A(1:end,:) == A(hrry(end),1));
[a1, b1]=find(A(1:end,:) == A(hrry(end),2));
[a2, b2]=find(A(1:end,:) == A(hrry(end),3));
int1= intersect(a,a1);
int2= intersect(a,a2);
int3= intersect(a1,a2);
ints=[int1;int2;int3];
ints= unique(ints);
[Lia,Locb] = ismember(ints(1:end,:),gr(1:end,:));
[z, x]=find(Lia(1:end,:) == 1);
ints(z(1:end),:)=[];
tg=[a;a1;a2];
if isempty(ints)
f= setdiff(tg,gr);
if isempty(f)
Anb=1:m;
Anbc=Anb';
nwf= setdiff(Anbc,gr);
gr=[gr;nwf(1,:)];
else
gr=[gr;f(1,:)];
end
else
gr=[gr;ints(end)];
end
nwrry= [nwrry;A(gr(end),:)];
end
Related
I'm a total beginner when it comes to MATLAB, so I have a question for this. How am I supposed to write this code out and if by any chance, can someone be kind enough to write out the code because I've been struggling with this. Use loops to create 3 x 5 matrix in which the value of each element is half of its row number plus three times its column number. for instance, the value of element (2,5) is: 1/22+35
The nested loops control the indexing of the matrix. The outer for-loop traverses through the rows of the matrix and the inner for-loop traverses through the columns of the matrix.
The second part of this question requires using a combination of the looping/scanning variables Row and Column to set the value of the matrix:
Matrix Value = (Row ÷ 2) + (3 × Column)
Number_Of_Rows = 3;
Number_Of_Columns = 5;
Matrix = zeros(Number_Of_Rows,Number_Of_Columns);
%Running through the array indices using two loops%
for Row = 1: Number_Of_Rows
for Column = 1: Number_Of_Columns
%Evaluating the value based on the current row and column index%
Matrix(Row,Column) = (Row/2) + (3*Column);
end
end
Matrix
Result:
Looping Methodology:
Variable Matrix Opened In Workspace:
Here's an intuitive way to do this:
% Initialize row num and column num
row = 3;
column = 5;
% H is the matrix of desire
% Initialize it as a 3*5 zero matrix
H = zeros(3,5);
% Outer loop, over column index
% Remember Matlab's index start with 1 not 0
for c = 1:column
% Inner Loop, over row index
for r = 1:row
% The algorithm of each element in the matrix
H(r,c) = 0.5*r+3*c;
end
end
So I want to concatenate an m x n matrix to obtain a 1 x mn matrix. The matrix I want to concatenate are generated from a while loop. Although the number of columns will always be 3, I however cannot tell how many rows there will be for each iteration. Also, the row sizes for each iteration may not always be the same.
The code runs in cases where the row sizes were all equal to 6, but in cases where they aren't equal I get an error:
Error using vertcat Dimensions of matrices being concatenated are not consistent.
parts of the code are as follows:
A = [];
B = [];
searchArea = 2;
for ii = 1: numel(velocity)
Do ....
while area(ii,:) < searchArea
Do ....
% COLLATE vectors for A
A = [A; [Ax(ii), Ay(ii), Az(ii)]];
Do ...
end
%# Copy the A into new variable (B) and Reshape into row vector so as to associate each row to its corresponding velocity
B = [B; reshape(A.',1,[])];
A = [];
end
Could someone please advice me on what I am doing wrong here. I would clarify further if there be need. Thanks guys!
If it's your intent that B ends up being a row vector, then you need to change this:
B = [B; reshape(A.',1,[])]; % Does vertical concatenation
to this:
B = [B reshape(A.',1,[])]; % Does horizontal concatenation (note there's no semicolon)
so that each row vector gotten from reshaping A gets added to the end of the row instead of as a new row (as the semicolon indicates).
I have an N-by-M-Matrix as input called GR wich consists of the following numbers: -3,0,2,4,7,10,12
And I have to return a vector. If M=1, then it should just return the input.
If M>1 It should remove the lowest number from the matrix and then calculate the mean of the remaining numbers.
However, if one of the numbers in the row is -3, it should return the value -3 in the output.
My thoughts of the problem:
Is it possible to make a for loop?
for i=1:length(GR(:,1))
If length(GR(1,:))==1
GR=GR
end
If length(GR(1,:))>1
x=min(GR(i,:))=[] % for removing the lowest number in the row
GR=sum(x)/length(x(i,:))
I just don't have any Idea of how to detect if any of the numbers in the row is -3 and then return that value instead of calculating the mean and when I tried to delete the lowest number in the matrix using x=min(GR(i,:)) matlab gave me this error massage 'Deletion requires an existing variable.'
I put in a break function. As soon as it detects a -3 value it breaks from the loop. Same goes for the other function.
Note that it is an i,j (M*N) matrix. So you might need to change your loop.
for i=1:length(GR(:,1))
if GR(i,1)==-3
GR=-3
break
end
If length(GR(1,:))==1
GR=GR
break
end
If length(GR(1,:))>1
x=min(GR(i,:))=[] % for removing the lowest number in the row
GR=sum(x)/length(x(i,:))
end
end
you can use Nan's, nanmean, any, and dim argument in these functions:
% generate random matrix
M = randi(3);
N = randi(3);
nums = [-3,0,2,4,7,10,12];
GR = reshape(randsample(nums,N*M,true),[N M]);
% computation:
% find if GR has only one column
if size(GR,2) == 1
res = GR;
else
% find indexes of rows with -3 in them
idxs3 = any(GR == -3,2);
% the (column) index of the min. value in each row
[~,minCol] = min(GR,[],2);
% convert [row,col] index pair into linear index
minInd = sub2ind(size(GR),1:size(GR,1),minCol');
% set minimum value in each row to nan - to ignore it on averaging
GR(minInd) = nan;
% averaging each rows (except for the Nans)
res = nanmean(GR,2);
% set each row with (-3) in it to (-3)
res(idxs3) = -3;
end
disp(res)
I have sum of 3 cell arrays
A=72x1
B=72x720
C=72x90
resultant=A+B+C
size of resultant=72x64800
now when I find the minimum value with row and column indices I can locate the row element easily but how can I locate the column element in variables?
for example
after dong calculations for A,B,C I added them all and got a resultant in from of <72x(720x90)> or can say a matrix of integers of size <72x64800> then I found the minimum value of resultant with row and column index using the code below.
[minimumValue,ind]=min(resultant(:));
[row,col]=find(result== minimumValue);
then row got 14 and column got 6840 value..
now I can trace row 14 of all A,B,C variables easily but how can I know that the resultant column 6480 belongs to which combination of A,B,C?
Instead of using find, use the ind output from the min function. This is the linear index for minimumValue. To do that you can use ind2sub:
[r,c] = ind2sub(size(resultant),ind);
It is not quite clear what do you mean by resultant = A+B+C since you clearly don't sum them if you get a bigger array (72x64800), on the other hand, this is not a simple concatenation ([A B C]) since this would result in a 72x811 array.
However, assuming this is a concatenation you can do the following:
% get the 2nd dimension size of all matrices:
cols = cellfun(#(x) size(x,2),{A,B,C})
% create a vector with reapiting matrices names for all their columns:
mats = repelem(['A' 'B' 'C'],cols);
% get the relevant matrix for the c column:
mats(c)
so mats(c) will be the matrix with the minimum value.
EDIT:
From your comment I understand that your code looks something like this:
% arbitrary data:
A = rand(72,1);
B = rand(72,720);
C = rand(72,90);
% initializing:
K = size(B,2);
N = size(C,2);
counter = 1;
resultant = zeros(72,K*N);
% summing:
for k = 1:K
for n = 1:N
resultant(:,counter) = A + B(:,k) + C(:,n);
counter = counter+1;
end
end
% finding the minimum value:
[minimumValue,ind] = min(resultant(:))
and from the start of the answer you know that you can do this:
[r,c] = ind2sub(size(resultant),ind)
to get the row and column of minimumValue in resultant. So, in the same way you can do:
[Ccol,Bcol] = ind2sub([N,K],c)
where Bcol and Ccol is the column in B and C, respectively, so that:
minimumValue == A(r) + B(r,Bcol) + C(r,Ccol)
To see how it's working imagine that the loop above fills a matrix M with the value of counter, and M has a size of N-by-K. Because we fill M with a linear index, it will be filled in a column-major way, so the row will correspond to the n iterator, and the column will correspond to the k iterator. Now c corresponds to the counter where we got the minimum value, and the row and column of counter in M tells us the columns in B and C, so we can use ind2sub again to get the subscripts of the position of counter. Off course, we don't really need to create M, because the values within it are just the linear indices themselves.
Let's say we have three m-by-n matrices of equal size: A, B, C.
Every column in C represents a time series.
A is the running maximum (over a fixed window length) of each time series in C.
B is the running minimum (over a fixed window length) of each time series in C.
Is there a way to determine T in a vectorized way?
[nrows, ncols] = size(A);
T = zeros(nrows, ncols);
for row = 2:nrows %loop over the rows (except row #1).
for col = 1:ncols %loop over the columns.
if C(row, col) > A(row-1, col)
T(row, col) = 1;
elseif C(row, col) < B(row-1, col)
T(row, col) = -1;
else
T(row, col) = T(row-1, col);
end
end
end
This is what I've come up with so far:
T = zeros(m, n);
T(C > circshift(A,1)) = 1;
T(C < circshift(B,1)) = -1;
Well, the trouble was the dependency with the ELSE part of the conditional statement. So, after a long mental work-out, here's a way I summed up to vectorize the hell-outta everything.
Now, this approach is based on mapping. We get column-wise runs or islands of 1s corresponding to the 2D mask for the ELSE part and assign them the same tags. Then, we go to the start-1 along each column of each such run and store that value. Finally, indexing into each such start-1 with those tagged numbers, which would work as mapping indices would give us all the elements that are to be set in the new output.
Here's the implementation to fulfill all those aspirations -
%// Store sizes
[m1,n1] = size(A);
%// Masks corresponding to three conditions
mask1 = C(2:nrows,:) > A(1:nrows-1,:);
mask2 = C(2:nrows,:) < B(1:nrows-1,:);
mask3 = ~(mask1 | mask2);
%// All but mask3 set values as output
out = [zeros(1,n1) ; mask1 + (-1*(~mask1 & mask2))];
%// Proceed if any element in mask3 is set
if any(mask3(:))
%// Row vectors for appending onto matrices for matching up sizes
mask_appd = false(1,n1);
row_appd = zeros(1,n1);
%// Get 2D mapped indices
df = diff([mask_appd ; mask3],[],1)==1;
cdf = cumsum(df,1);
offset = cumsum([0 max(cdf(:,1:end-1),[],1)]);
map_idx = bsxfun(#plus,cdf,offset);
map_idx(map_idx==0) = 1;
%// Extract the values to be used for setting into new places
A1 = out([df ; false(1,n1)]);
%// Map with the indices obtained earlier and set at places from mask3
newval = [row_appd ; A1(map_idx)];
mask3_appd = [mask_appd ; mask3];
out(mask3_appd) = newval(mask3_appd);
end
Doing this vectorized is rather difficult because the current row's output depends on the previous row's output. Doing vectorized operations usually means that each element should stand out on its own using some relationship that is independent of the other elements that surround it.
I don't have any input on how you would achieve this without a for loop but I can help you reduce your operations down to one instead of two. You can do the assignment vectorized per row, but I can't see how you'd do it all in one shot.
As such, try something like this instead:
[nrows, ncols] = size(A);
T = zeros(nrows, ncols);
for row = 2:nrows
out = T(row-1,:); %// Change - Make a copy of the previous row
out(C(row,:) > A(row-1,:)) = 1; %// Set those elements of C
%// in the current row that are larger
%// than the previous row of A to 1
out(C(row,:) < B(row-1,:)) = -1; %// Same logic but for B now and it's
%// less than and the value is -1 instead
T(row,:) = out; %// Assign to the output
end
I'm currently figuring out how to do this with any loops whatsoever. I'll keep you posted.