Matlab find minimum value by ignoring zero and certain condition - matlab

so i have this data
yi =
-1
1
1
-2
4
data=
1.0000 0 1.0000 0.2000 1.0000 1.0000
0 0 0 0.5000 1.0000 1.0000
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000
0 0 0 0 1.0000 0
1.0000 0 0 0 1.0000 0
and i short that data become like this
sdata =
0 0.2000 1.0000 1.0000 1.0000 1.0000
0 0 0 0.5000 1.0000 1.0000
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000
0 0 0 0 0 1.0000
0 0 0 0 1.0000 1.0000
with this rule
if yi >= 0 then output = max row sdata
if yi < 0 theris 2 conditions:
a. if sdata member only 0 and 1 then output = min row sdata =0
b. if sdata member including number between 0 and 1 then output = min sdata except zero
so i want to find an output like this
output=
0.2000
1.0000
1.0000
1.0000
0
1.0000
i still stuck to this point
for i=1:5
if yi(i)>=0
output(i)=max(sdata(i,:));
else
output(i)=min(sdata(i,:));
end;
end;
outputnya=output'

Try this:
else
minVal = min(sdata(i,sdata(i,:)>0))
if minVal == 1
output(i)=min(sdata(i,:));
else
output(i) = minVal;
end;
end;
Explanation: sdata(i,:)>0 returns table of 0 and 1, sdata(i,sdata(i,:)>0) returns element which meet specified condition.

Related

How to find non zero minimum array in a 2D matrix in matlab

I have a 2D matrix as shown below:
A =
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.8193 0.6429 0.4731
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.8172 0.6395 0.4696
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.8099 0.6285 0.4582
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.7938 0.6066 0.4364
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.7588 0.5675 0.4006
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.8527 0.6739 0.5039 0.3477
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.8825 0.7371 0.5803 0.4264 0.2807
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.7928 0.6327 0.4838 0.3406 0.2054
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.8846 0.7945 0.6560 0.5173 0.3816 0.2469 0.1131
1.0000 1.0000 1.0000 1.0000 1.0000 0.8598 0.7438 0.6373 0.5194 0.3988 0.2785 0.1522 0
1.0000 1.0000 1.0000 0.8710 0.7956 0.6954 0.5935 0.4916 0.3856 0.2799 0.1814 0.0834 0
0.7915 0.7845 0.7581 0.6884 0.6159 0.5326 0.4432 0.3500 0.2514 0.1538 0.0838 0 0
0.5972 0.5882 0.5596 0.5085 0.4471 0.3760 0.2967 0.2137 0.1163 0 0 0 0
0.4208 0.4116 0.3836 0.3389 0.2881 0.2274 0.1540 0.0919 0 0 0 0 0
0.2629 0.2536 0.2244 0.1755 0.1388 0.0915 0 0 0 0 0 0 0
0.1235 0.1155 0.0850 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
I want to remove its zero arrays and then find the minimum value of each column and put those minimum values in a vector.
I just used find(A ~= 0) but it's not working.
How can I do that?
Replace all of the zeroes with NaN, then apply min to each column independently. Setting values to NaN in a matrix / vector allows min to ignore those values, so you'd effectively be ignoring the zeroes. Assuming that your matrix is in A, do this:
Anan = A;
Anan(A == 0) = NaN;
out = min(Anan, [], 1);

How to find a set of maximum independent vectors given a matrix?

Given a matrix A, I want to find a set of maximum linearly independent columns ? I have tried use rref(A) in matlab, then find all the pivot, it works well in general matrix. But when the matrix is special, it seems given the wrong answer, for example A =
1.6180 1.0000 1.0000 1.0000 0 1.0000
1.0000 1.6180 1.0000 1.0000 1.0000 0
1.0000 1.0000 1.6180 0 1.0000 1.0000
1.0000 1.0000 0 1.6180 0 0
0 1.0000 1.0000 0 1.6180 0
1.0000 0 1.0000 0 0 1.6180
then the rref(A)=
1.0000 0 0 0 0 0.8730
0 1.0000 0 0 0 -1.6180
0 0 1.0000 0 0 0.7450
0 0 0 1.0000 0 0.4604
0 0 0 0 1.0000 0.5396
0 0 0 0 0 0
this cannot be right. because the rank(A)=4. I have done the search, someone said that rref is not accurate and SVD will help ? but I really don't know how to do it ? Help me with the example matrix A will help me much more. 3Q !

Blockdiagonal variation grid

I have the feeling I am missing something intuitive in my solution for generating a partially varied block-diagonal grid. In any case, I would like to get rid of the loop in my function (for the sake of challenge...)
Given tuples of parameters, number of intervals and percentage variation:
params = [100 0.5 1
24 1 0.9];
nint = 1;
perc = 0.1;
The desired output should be:
pspacegrid(params,perc,nint)
ans =
90.0000 0.5000 1.0000
100.0000 0.5000 1.0000
110.0000 0.5000 1.0000
100.0000 0.4500 1.0000
100.0000 0.5000 1.0000
100.0000 0.5500 1.0000
100.0000 0.5000 0.9000
100.0000 0.5000 1.0000
100.0000 0.5000 1.1000
21.6000 1.0000 0.9000
24.0000 1.0000 0.9000
26.4000 1.0000 0.9000
24.0000 0.9000 0.9000
24.0000 1.0000 0.9000
24.0000 1.1000 0.9000
24.0000 1.0000 0.8100
24.0000 1.0000 0.9000
24.0000 1.0000 0.9900
where you can see that the variation occurs at the values expressed by this mask:
mask =
1 0 0
1 0 0
1 0 0
0 1 0
0 1 0
0 1 0
0 0 1
0 0 1
0 0 1
1 0 0
1 0 0
1 0 0
0 1 0
0 1 0
0 1 0
0 0 1
0 0 1
0 0 1
The function pspacegrid() is:
function out = pspacegrid(params, perc, nint)
% PSPACEGRID Generates a parameter space grid for sensitivity analysis
% Size and number of variation steps
sz = size(params);
nsteps = nint*2+1;
% Preallocate output
out = reshape(permute(repmat(params,[1,1,nsteps*sz(2)]),[3,1,2]),[],sz(2));
% Mask to index positions where to place interpolated
[tmp{1:sz(2)}] = deal(true(nsteps,1));
mask = repmat(logical(blkdiag(tmp{:})),sz(1),1);
zi = cell(sz(1),1);
% LOOP per each parameter tuple
for r = 1:sz(1)
% Columns, rows, rows to interpolate and lower/upper parameter values
x = 1:sz(2);
y = [1; nint*2+1];
yi = (1:nint*2+1)';
z = [params(r,:)*(1-perc); params(r,:)*(1+perc)];
% Interpolated parameters
zi{r} = interp2(x,y,z, x, yi);
end
out(mask) = cat(1,zi{:});
I think I got it, building off your pre-loop code:
params = [100 0.5 1
24 1 0.9];
nint = 1;
perc = 0.1;
sz = size(params);
nsteps = nint*2+1;
% Preallocate output
out = reshape(permute(repmat(params,[1,1,nsteps*sz(2)]),[3,1,2]),[],sz(2));
%Map of the percentage moves
[tmp{1:sz(2)}] = deal(linspace(-perc,perc,nint*2+1)');
mask = repmat(blkdiag(tmp{:}),sz(1),1) + 1; %Add one so we can just multiply at the end
mask.*out
So instead of making your mask replicate the ones I made it replicate the percentage moves each element makes which is a repeating pattern, the basic element is made like this:
linspace(-perc,perc,nint*2+1)'
Then it's as simple as adding 1 to the whole thing and multiplying by your out matrix
I tested it as follows:
me = mask.*out;
you = pspacegrid(params, perc, nint);
check = me - you < 0.0001;
mean(check(:))
Seemed to work when I fiddled with the inputs. However I did get an error with your function, I had to change true(...) to ones(...). This might be because I'm running it online which probably uses Octave rather than Matlab.

Plot a disc in Matlab, color varying with angle

I would like to represent some data depending on the angle of measure. I have something like that:
angle=[0 90 180 270 360];
value=[1 2 3 4];
In my case, length(angle)=73
How can I plot a disc in which the color of the radius line varies according to the vector value.
I would like something like imagesc but in a disc.
I unsuccessfully tried using rose, but it is limited to a max of 20 angles.
This is another alternative that does not use 3D graphics, only 2D. It uses the primitive patch command that draws triangles. Here is a result:
function PlotDisc
thetas=(0:5:360)'*pi/180;
% r=(0:0.1:1)';
r = 1;
[x,y]=pol2cart(thetas,r);
colMap = GetColMap();
for i=1:numel(x)-1
X = [0 x(i) x(i+1) 0];
Y = [0 y(i) y(i+1) 0];
col = i / (numel(x)-1) * numel(colMap);
patch(X,Y,col,'EdgeAlpha',0);
end
axis equal
end
function colMap = GetColMap()
colMap = ...
[0.0417 0 0
0.0833 0 0
0.1250 0 0
0.1667 0 0
0.2083 0 0
0.2500 0 0
0.2917 0 0
0.3333 0 0
0.3750 0 0
0.4167 0 0
0.4583 0 0
0.5000 0 0
0.5417 0 0
0.5833 0 0
0.6250 0 0
0.6667 0 0
0.7083 0 0
0.7500 0 0
0.7917 0 0
0.8333 0 0
0.8750 0 0
0.9167 0 0
0.9583 0 0
1.0000 0 0
1.0000 0.0417 0
1.0000 0.0833 0
1.0000 0.1250 0
1.0000 0.1667 0
1.0000 0.2083 0
1.0000 0.2500 0
1.0000 0.2917 0
1.0000 0.3333 0
1.0000 0.3750 0
1.0000 0.4167 0
1.0000 0.4583 0
1.0000 0.5000 0
1.0000 0.5417 0
1.0000 0.5833 0
1.0000 0.6250 0
1.0000 0.6667 0
1.0000 0.7083 0
1.0000 0.7500 0
1.0000 0.7917 0
1.0000 0.8333 0
1.0000 0.8750 0
1.0000 0.9167 0
1.0000 0.9583 0
1.0000 1.0000 0
1.0000 1.0000 0.0625
1.0000 1.0000 0.1250
1.0000 1.0000 0.1875
1.0000 1.0000 0.2500
1.0000 1.0000 0.3125
1.0000 1.0000 0.3750
1.0000 1.0000 0.4375
1.0000 1.0000 0.5000
1.0000 1.0000 0.5625
1.0000 1.0000 0.6250
1.0000 1.0000 0.6875
1.0000 1.0000 0.7500
1.0000 1.0000 0.8125
1.0000 1.0000 0.8750
1.0000 1.0000 0.9375
1.0000 1.0000 1.0000] ;
end
Some time ago I had to plot polar data and looked for something similar. I do not know if it corresponds to your needs but I adapted my solution to your problem, here it is:
theta=(0:360)'*pi/180;
r=(0:0.1:1)';
value=repmat([360 (1:360)],size(r,1),1);
[THETA,R]=meshgrid(theta,r);
[X,Y]=pol2cart(THETA,R);
surf(X,Y,value,'edgecolor','none');
view(0,90);
UPDATE: You are absolutely right Andrey, and I suspect the 3D graphics to take more memory and thus display a lot slower but at the time I did not find any ohter way. Your solution is better, I will use it from now. The only thing I would change is the for loop:
r=1;
dtheta=0.01;
theta=linspace(0,2*pi,100)';
n=numel(theta);
[x,y]=pol2cart(theta,r);
figure;
cmap=colormap(jet);
X=[zeros(1,n-1);x(1:end-1)';x(2:end)';zeros(1,n-1)];
Y=[zeros(1,n-1);y(1:end-1)';y(2:end)';zeros(1,n-1)];
C=numel(cmap)*(1:n-1)/n-1;
patch(X,Y,C,'EdgeAlpha',0);
axis equal;

Syntax error for rectangular image

There is an image X of N*M size row M,column N. There are other 2 images A,B of same size as X. The objective is to shuffle the rows of X with the rows extracted from A and shuffle the columns of X with the columns extracted from B resulting in a totally modified img.
I am stuck at the point where simultaneously this is occuring. I am aware about the colon operator with which the code runs but for a square image. Please help how to go about it.
X=imread('picture.jpg');
[r c]=size(X);
[dummy,rowscrambleIdx]=sort(A,1);
X_shuffled=X;
[dummy,colscrambleIdx]=sort(B,2);
EDIT: The following code works for square image and I want to do similar operation for a rectangular sized image. However, this code does not work for rectangular sized image. I have tried to make the first code follow a similar logic but it does not work for a non-square RGB image having say 256*240*3 size
X=imread('picture.jpg');
[dummy,scrambleIdx]=sort(A(:));
X_shuffled=X;
X_shuffled(:)=A(scrambleIdx);
%now unscrambling
[dummy,unscrambleIdx] = sort(scrambleIdx);
X_recovered=X;
X_recovered(:)=X_shuffled(unscrambleIdx);
Why not use randi to randomly create some number of indicies to pull from A, and some to pull from B?
Example:
m=10;
n=5;
A=rand(m,n)
B=ones(m,n)
%3x1 vector of random ints b/w 1 and 10
index=randi([1 10],3,1);
rand_row = A(index,:);
B(index,:)=rand_row
Then output is:
index =
10
9
4
A =
0.9797 0.1174 0.7303 0.6241 0.2619
0.4389 0.2967 0.4886 0.6791 0.3354
0.1111 0.3188 0.5785 0.3955 0.6797
0.2581 0.4242 0.2373 0.3674 0.1366
0.4087 0.5079 0.4588 0.9880 0.7212
0.5949 0.0855 0.9631 0.0377 0.1068
0.2622 0.2625 0.5468 0.8852 0.6538
0.6028 0.8010 0.5211 0.9133 0.4942
0.7112 0.0292 0.2316 0.7962 0.7791
0.2217 0.9289 0.4889 0.0987 0.7150
B =
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
B =
1.0000 1.0000 1.0000 1.0000 1.0000
1.0000 1.0000 1.0000 1.0000 1.0000
1.0000 1.0000 1.0000 1.0000 1.0000
0.2581 0.4242 0.2373 0.3674 0.1366
1.0000 1.0000 1.0000 1.0000 1.0000
1.0000 1.0000 1.0000 1.0000 1.0000
1.0000 1.0000 1.0000 1.0000 1.0000
1.0000 1.0000 1.0000 1.0000 1.0000
0.7112 0.0292 0.2316 0.7962 0.7791
0.2217 0.9289 0.4889 0.0987 0.7150