how do I find the closest value to a given number in an array? - matlab

The Situation is as follows:
I have to arrays, symbolizing a positive domain x, and another array whose a function of that domain z
Now, I want, for a given point y, to find the z value in the nearest location. For thatI wrote the following function:
R0 = #(y) z(find(abs( abs(y). - r) == min(abs(abs(y). - r))))
(The use of abs is for negative values of y, since z is symmetric)
This works perfectally well, unless y is a vector. So, if I use the following code:
y = [-1:0.01:1];
R0(y);
I get the following error:
Error using ==
Matrix dimensions must agree.
Trying to debug it, I came to see that the find statement returned a 1*0 matrix, hence nothing. This is although the value of y ACTUALLY EXSIST in the r array.
What I really want is to get a new vector, which assign the nearest value in z for each value of y.
Other, totally different solutions might be used, so I prefer understanding why this solution doesn't work and how can I make it work.
Thanks

Your question is not very clear. If I understand correctly, for each element of y you want to find the closest element in z.
y = [1 2 3 4 5]; %// example data
z = [0 2.5 6]; %// example data
d = abs(bsxfun(#minus, y(:).', z(:))); %'// compute distance for all pairs
[~, ind] = min(d); %// index of minimizer in z for each value of y
result = z(ind);
In this example,
result =
0 2.5000 2.5000 2.5000 6.0000

I am assuming that all of r,z,y are row vectors;
According to the code you provided, it looks like you need the value in z whose index is same as the index of the value in r closest to scalar y. The following code does the same for a row vector y.
function output = some_fun(r,z,y)
%// column i of temp is abs(r - y(i))
temp = abs(repmat(abs(y),size(r,2),1) - repmat(r',1,size(y,2))) % // it is a size(r,2) x size(y,2) matrix
%// each column i of min_ has min(abs(r - y(i))) as all its entries
min_ = repmat(min(temp),size(r,2),1); % // it is a size(r,2) x size(y,2) matrix
%// each column i of ind1 has value of 1 corresponding to the index of closest element of r to y(i) and zero for others
ind1 = temp == min;
%// row_(i) is the row index of ind1 where the value is 1 for column i in ind1.
[row_ col_] = find(ind1);
%// thus row_(i) is the index of element of r closest to y(i)
output = z(1,row_);
end

Related

How can I find a specific point in a figure in MATLAB?

I want a specific value in the figure in MATLAB. I put the black circle and arrow manually through the figure insert option. But How can I set the value now?
I want the x-axes values that are exactly 90% of each CDF curve.
here I am attaching my MatLab figure in jpg mode.
I would use interp1 to find the value. I'll assume that your x variable is called x and your cdf value is called c. You can then use code like this to get the x value where c = 0.9. This will work even if you don't have a cdf value at exactly 0.9
x_at_0p9 = interp1(c, x, 0.9);
You plotted those figures by using:
plot(X,Y)
So, your problem is to find x_0 value that makes Y = 0.9.
You can do this:
ii = (Y==0.9) % finding index
x_0 = X(ii) % using index to get x_0 value
Of course this will only work if your Y vector has exactly the 0.9 value.
As this is not always the case you may want to get the x_0 value that first makes Y to be greater or equal than 0.9.
Then you can do this:
ii = find(Y>=0.9, 1) % finding index
x_0 = X(ii) % using index to get x_0 value
Assuming that your values are x and Y (where x is a vector and the same for all curves) and Y is a matrix with the same number of rows and as many columns as there are curves; you just need to find the first point where Y exceeds 0.9:
x = (0:0.01:pi/2)'; % time vector
Y = sin(x*rand(1,3))*10; % value matrix
% where does the values exceed 90%?
lg = Y>= 0.9;
% allocate memory
XY = NaN(2,size(Y,2));
for i = 1:size(Y,2)
% find first entry of a column, which is 1 | this is an index
idx = find(lg(:,i),1);
XY(:,i) = [x(idx);Y(idx,i)];
end
plot(x,Y, XY(1,:),XY(2,:), 'o')

How do I create a plot that represents a sum of sinusoids without a loop?

How can I make a simple plot of function y = sin(x) + sin(3x) + ... + sin(100x) without using any loops?
Yes, it's possible by using a call to bsxfun to generate the right points to be applied per sinusoid, then using a sum call to sum all of the sinusoids for each point. You'd then plot this normally.
Something like this comes to mind:
x = -5:0.01:5; %// Define x points here
pts = bsxfun(#times, 1:2:101, x(:)); %// Generate a grid of points
y = sum(sin(pts), 2); %// Compute the y values for each x value
plot(x(:),y); %// Plot the result
The first line of code generates a set of x values that you wish to plot. The next line of code generates a 2D grid of points. Each row applies x, 3*x, 5*x, ..., 101*x for one particular point in x. Each column represents one unique x point. As such, when we use sum (next line), we also apply the sin operator to each of these individual points on the grid, then go ahead and sum over each row to produce the output for each unique point of x. We then plot the results.
Note that I used x(:) to unroll the x vector so that it's a column vector. This is needed for the code to work. This also allows you to make x a row or column vector and the code will still work.
This is the plot I get:
Use cumsum.
octave:1> x = 1;
octave:2> sin(x)
ans = 0.841470984807897
octave:3> sin(x*1)
ans = 0.841470984807897
octave:4> sin(x*1) + sin(x*2)
ans = 1.75076841163358
octave:5> sin(x*1) + sin(x*2) + sin(x*3)
ans = 1.89188841969345
octave:6> cumsum(sin(x * (1:3)))
ans =
0.841470984807897 1.75076841163358 1.89188841969345

Matlab: how to run a For loop with multiple outputs?

So my question refers to the regress() function in matlab. Click here for the Matlab documentation
If I want to run multiple regressions using this function and output both the coefficients and the confidence intervals, what's the best way to do this in a For loop?
Matlab's own syntax for this is [b,bint] = regress(y,X). But when I try to implement this in a for loop it tells me that the dimension mismatch. My code is the following:
for i=1:6
[a, b]=regress(Dataset(:,i),capm_factors);
capm_coefs(i,:)=a;
capm_ci(i,:)=b;
end
Please help, thanks!
regress outputs a column vector of coefficients that minimize the least squared error between your input data (capm_factors) and your predicted values (Dataset(:,i)). However, in your for loop, you are assuming that a and b are row vectors.
Also, the first output of regress is the solution to your system, but the second output contains a matrix of confidence values where the first column denotes the lower end of the confidence interval for each variable and the second column denotes the upper end of the confidence interval.
Specifically, your input capm_factors should be a M x N matrix where M is the total number of input samples and N is the total number of features. In your code, a would thus give you a N x 1 vector and b would give you a N x 2 matrix.
If you'd like use a loop, make sure capm_coefs is a N x l matrix where l is the total number of times you want to loop and capm_ci should either be a N x 2 x l 3D matrix or perhaps a l element cell array. Either way is acceptable.... but I'll show you how to do both.
Something like this comes to mind:
Confidences as a 3D matrix
l = 6; %// Define # of trials
[M,N] = size(capm_factors); %// Get dimensions of data
capm_coefs = zeros(N, l);
capm_ci = zeros(N, 2, l);
for ii = 1 : l
[a,b] = regress(Dataset(:,i), capm_factors);
capm_coefs(:,ii) = a;
capm_ci(:,:,ii) = b;
end
You'd then access the coefficients for a trial via capm_coefs(:,ii) where ii is the iteration you want. Similarly, the confidence matrix can be accessed via capm_ci(:,:,ii)
Confidences as a cell array
l = 6; %// Define # of trials
[M,N] = size(capm_factors); %// Get dimensions of data
capm_coefs = zeros(N, l);
capm_ci = cell(l); %// Cell array declaration
for ii = 1 : l
[a,b] = regress(Dataset(:,i), capm_factors);
capm_coefs(:,ii) = a;
capm_ci{ii} = b; %// Assign confidences to cell array
end
Like above, you'd access the coefficients for a trial via capm_coefs(:,ii) where ii is the iteration you want. However, the confidence matrix can be accessed via capm_ci{ii} as we are now dealing with cell arrays.

How to find N values of 3D matrix that satisfy condition

I have a 3D array that is denoted by features. Each element of feature is a number x. Now I will get that number and calculate g(x) and f(x) of the number (g and f are functions of x). My problem is how to get N maximization of absolute value between g(x) and f(x). The function will return an array with N elements x. But I don't know how to get them. Could you help me?
This is my code:
%features is 3D array
%N is elements that we need
%Fs,sigmas,thetas are size of the array
% return N elements of features that maximization abs(f_s-g_s)
function features_filter=gabor_sort(features,N,Fs,sigmas,thetas)
for k = 1:numel(sigmas)
for j = 1:numel(Fs)
for i = 1:numel(thetas)
x= features(:,:,k,j,i);
f_x=x.^2;
g_x=x.^3+1;
s1=abs(f_x-g_x);
%%Do something in here to get maximization of s1
end
end
end
end
This isn't a problem. Create two matrices that will store the features we get for each combination of sigma, Fs and theta, as well as place your absolute values for each feature in this matrix, and when you're done, sort these distances in descending order. We can then use the second parameter of sort to give us the location of the features that maximize this distance. In other words, do this:
%features is 3D array
%N is elements that we need
%Fs,sigmas,thetas are size of the array
% return N elements of features that maximization abs(f_x-g_x)
function features_filter=gabor_sort(features,N,Fs,sigmas,thetas)
s1 = []; % s1 array to store our distances
xFeatures = []; %// Features to return
for k = 1:numel(sigmas)
for j = 1:numel(Fs)
for i = 1:numel(thetas)
x = features(:,:,k,j,i);
xFeatures = cat(3,xFeatures,x); %// Stack features in a 3D matrix
x = x(:); %// Convert to 1D as per your comments
f_x=mean(x.^2); %// Per your comment
g_x=mean(x.^3+1); %// Per your comment
s1 = [s1 abs(f_x-g_x)]; %// Add to s1 array
end
end
end
[~,sortInd] = sort(s1, 'descend');
%// Return a 3D matrix where each slice is a feature matrix
%// The first slice is the one that maximized abs(f_x - g_x) the most
%// The second slice is the one that maximized abs(f_x - g_x) the second most, etc.
features_filter = xFeatures(:,:,sortInd(1:N));
Minor note: This code is untested. I don't have access to your data, so I can't really reproduce. Hope this works!

Matlab - relational matricies?

I have a vector of coordinates called x. I want to get the element(s) with the min y coordinate:
a = find(x(:,2)==min(x(:,2))); % Contains indices
This returns the indexes of the elements with the smallest y coordinates. I say element*s* because sometimes this would return more than 1 value (e.g. (10,2) and (24,2) both have 2 as y coordinate and if 2 is the min y coordinate...).
Anyway, my next step is to sort (ascending) the elements with the min y coordinates according to their x coordinates. First I do:
b = sort(x(a,1));
The above operation might rearrange the elements with min y coordinates so I want to apply this rearrangement to a as well. So I do:
[v i] = ismember(b, x(:, 1));
Unfortunately, if there are elements with the same x value but different y values and one of these elements turns out to be a member of a (i.e. b) then the above matrix chooses it. For example if (10,2) and (24,2) are the elements with smallest y coordinates and there is a 3rd element (24, 13) then it will mess up the above operation. Is there a better way? I wrote my script using loops and everything was fine but in line with Matlab's methodology I rewrote it and I fear my unfamiliarity with matlab is causing this error.
Sorry, I might have misunderstood your question but lemme rephrase what I think you want here:
You have a set of 2D coordinates:
x = [24,2; 10,2; 24,13];
You want the pairs of coordinates to stay together (24,2) (10,2) and (24,13). And you want to find the pairs of coordinates that has the min y-coordinate and if there are multiples, then you want to sort them by x-coordinate. And you want the row indices of what those coordinate pairs were in the original matrix x. So in other words, you want a final answer of:
v = [10,2; 24,2];
i = [2,1];
If I understood correctly, then this is how you can do it:
(Note: I changed x to have one more pair (40,13) to illustrate the difference between idx(i) and i)
>> x = [40,13; 24,2; 10,2; 24,13];
>> idx = find(x(:,2)==min(x(:,2))) %Same as what you've done before.
idx =
2
3
>> [v,i] = sortrows(x(idx,:)) %Use sortrows to sort by x-coord while preserving pairings
v =
10 2
24 2
i = % The indices in x(idx,:)
2
1
>> idx(i) %The row indices in the original matrix x
ans =
3
2
And finally, if this is not what you wanted, can you indicate what you think your answer [v,i] should be in the example you gave?