Find nearest set of values to a given value within an array - matlab

A =
0.75
0.6
0.62
0.51
0.53
0.48
Within such an array, how can one calculate the indices of x number of values closest to a given number? For example:
x = 0.5 %Given number
y = 3; %Number of values closest to (x) to extract
Here we wish to extract the three closest values to 0.5 - 0.51, 0.53 and 0.48.
[~,I] = min(abs(data-b));
c = data(I);
Is what I have thus far but this only extracts a single value - the absolute closest.

A = [0.75
0.6
0.62
0.51
0.53
0.48];
x = 0.5 %Given number
y = 3; %Number of values closest to (x) to extract
[~,c] = sort(abs(A-x));
yclosest=A(c(1:y));
This uses the second output of sort to index the original array A. First you subtract the number x from the array A and take the absolute value, as you had, then you sort that and take the lowest y numbers and use those to index A.

Sorting the absolute differences and choosing the three values that minimize this difference is the most canonical way to do it.... in fact, that's what I recommend.
However for the sake of completeness, if you can use toolboxes consider using knnsearch from the Statistics Toolbox and return the k=3 closest points. The output of knnsearch gives you the indices of the closest points. To find the actual points, index into A after:
A = [0.75
0.6
0.62
0.51
0.53
0.48];
x = 0.5;
y = 3;
IDX = knnsearch(A, x, 'K', y);
out = A(IDX);
We get:
>> out = A(IDX)
out =
0.5100
0.4800
0.5300

Related

Using fmincon in a way that the results are taken out of a vector which is set by myself

Is it possible to use fmincon so that the result is not a continuous x in a range lower_bound <= x <= upper_bound, but concrete numbers that I specify.
In my case, the matrix E is to be determined. Numbers in a vector such as V = [0.3 0.5 1] are to be distributed in the matrix E in such a way that another result C calculated with E becomes minimal.
An examples of possible result would be:
E = [ 0.3 0.3 0.5 1;
0.5 0.5 0.3 0.5;
1 0.3 0.3 0.5]

Binning Values from 2 variables using the same mean for each bin

How do I bin data from two different groups into bins centered around the same value?
As a toy example,
A(:,1) = [0.05:0.05:0.80]';
A(:,2) = [ones(7,1); [0.6; 0.6; 0.4]; zeros(6,1)];
B(:,1) = [0.15:0.1:0.95]';
B(:,2) = [ones(4,1); [0.8; 0.8; 0.2]; zeros(2,1)];
plot(A(:,1),A(:,2)); hold on; plot(B(:,1),B(:,2));
I'd like to bin and plot A and B on the same plot, but with the data binned at points 0.2, 0.4, 0.6, and 0.8 on the X-Axis for both A and B, meaning that there'll be uneven data in each bin. How should I go about group these values with a mean centered around those points?
Your request is a little bit unclear, but reading through the lines and your comment, I think this is what you were looking for:
edges = [0.2 0.4 0.6 1];
A(:,1) = (0.05:0.05:0.80).';
A(:,2) = [ones(7,1); [0.6; 0.6; 0.4]; zeros(6,1)];
[~,A_bins] = histc(A(:,1),edges);
[A_bin_vals,~,A_idx] = unique(A_bins);
A_avg = accumarray(A_idx,A(:,2),[numel(A_bin_vals) 1],#mean) ;
B(:,1) = (0.15:0.1:0.95).';
B(:,2) = [ones(4,1); [0.8; 0.8; 0.2]; zeros(2,1)];
[~,B_bins] = histc(B(:,1),edges);
[B_bin_vals,~,B_idx] = unique(B_bins);
B_avg = accumarray(B_idx,B(:,2),[numel(B_bin_vals) 1],#mean) ;
plot(0:3,A_avg,'-.r*'),hold on,plot(0:3,B_avg,'-.b*'),hold off;
xticks(0:3);
xticklabels({'0.2' '0.4' '0.6' '0.8'});
Output:
Actually, in order to accomplish this, I discretized the first column of your matrix applying the desired edges using histc. Then, using the accumarray function, I applied the mean function to all the value of the second column grouped by bin.

Retaining and identifying elements in an array which satisfy a threshold in MATLAB

I have a matrix (about 342 by 342) denoted by C_{ij} and I want to identify all indices i,j which satisfy the condition C_{ij} > rho where rho is some fixed value. I am using MATLAB
For example, if I have the matrix C_{ij} as:
C = 1 0.7 0.8
0.7 1 0.5
0.8 0.5 1
And rho = 0.6 then the indices which satisfy the condition C_{ij} > 0.6 are i,j = 1,2 as C_{11}=C_{22}=1 and C_{12}=C_{21}=0.7
But note that i,j=3 does not satisfy this condition since although C_{13}=C_{31}=0.8, C_{23}=C_{32}=0.5
I am not sure how/the best way to do this is in MATLAB?
C = rand(342,342);
rho = 0.6;
res = C(C>rho); %// contains all values that are above the threshold
[row,col,val] = find(res); %// returns the indices.
row would contain your i, col your j, but I'd caution against using i or j as a variable. val contains the corresponding value, but you can omit that for freeing RAM, as you can use C(row,col) as well to get the values.
If your matrix is symmetric you can use that:
[rowt,colt,val] = find(triu(C)>rho); %// find only in the upper triangle
row = [rowt;colt]; %// flip rows and columns to obtain all results
col = [colt;rowt]; %// flip rows and columns to obtain all results
For your edit:
IdxR = find(diff(unique(rows))==1,1,'first');
IdxC = find(diff(unique(columns))==1,1,'first');
Result = C(1:IdxR,1:IdxC);

Contour plot with 3 vector

I've a matrix M 10201x3 where the first 2 column are constant used to compute the response Z in column 3. Example:
.... ... .................
0.0031 0.02 0.792729854583740
0.0031 0.03 0.802729845046997
0.0031 0.04 0.812729895114899
0.0031 0.05 0.822729885578156
.... ... .................
0.0034 0.02 0.867461800575256
0.0034 0.03 0.877461791038513
0.0034 0.04 0.887461841106415
0.0034 0.05 0.897461831569672
0.0034 0.06 0.907461822032929
.... ... .................
I wanna make a contour plot where X = M(:,1), Y = M(:,2) and Z = M(:,3) with different colors for different hights. I need to do the same thing in both 2D and 3D.
I assume your data is regular, and you know how many repeating x-elements you have.
Let's call the number of repeating x = L - or you'll be able to find that out.
You need to reshape your vectors:
X = reshape(X,[],L);
Y = reshape(Y,[],L);
Z = reshape(Z,[],L);
You need Z how it is, but just the first row of X and the first column of Y.
X = X(:,1);
Y = Y(1,:);
and then you can use contour:
contour(X,Y,Z);
There is no need for interpolation!
contour(X,Y,Z), contour(X,Y,Z,n), and contour(X,Y,Z,v) draw contour
plots of Z using X and Y to determine the x- and y-axis limits.
If X and Y are vectors, then the length of X must equal the number of
columns in Z and the length of Y must equal the number of rows in Z.
If X and Y are matrices, then their sizes must equal the size of Z.
Therefore shorter:
X = X(1:L:end);
Y = Y(1:L);
Z = reshape(Z,[],L);
contour(X,Y,Z);
I would suggest to transform this array to three 2D arrays using interpolation with function griddata(). Interpolation could be useful for nonregular data. First, we create grid of coordinates:
xq=min(X):(max(X)-min(X))/200:max(X);
yq=min(Y):(max(Y)-min(Y))/200:max(Y);
[Xq, Yq] = meshgrid(xq,yq);
Than, we use interpolating:
Zq =griddata(X,Y,Z,Xq,Yq);
Than you can plot:
countour(Xq,Yq,Zq)

Unordered X Y coordinate pairs + Concentration contourplot

I have 2 vectors, X and Y, corresponding to a list of unordered coordinates, and a corresponding concentration vector C for each point.
I'd like to plot this on a structured grid as a 2D contour plot.
scatter3(X,Y,C,[],C);
gives me what I want visually, but I'm looking for 2D contours, i.e. pcolor. Is there an easy solution like griddata or trigriddata?
EDIT: Ok, so `scatter3(X,Y,C,[],C); view([0 90])ยด is the correct visual.
TriScatteredInterp works nicely for a rectangle. But what about an irregular shape like a map? :=)
F = TriScatteredInterp(x,y,C);
ty=0:0.005:0.284;
tx=0:0.005:0.65;
[qx,qy] = meshgrid(tx,ty);
qC = F(qx,qy);
pcolor(qx,qy,qC);
EXAMPLE: (X=width coordinate , Y= height coordinate, C= concentration of pollutant)
X Y C
0.1 0.0 5
0.1 0.1 10
0.1 0.21 5
0.2 0.1 4
0.2 0.3 1
0.2 0.5 2
0.2 0.51 7
0.3 0.15 4
0.3 0.36 6
0.3 0.5 3
0.3 0.52 7
scatter3(X,Y,C,[],C,'filled'); %individual plotting of X,Y pairs and colors=C
view([0 90]) %see only XY and Z becomes flat
Imagine we had 10000 XY pairs so scatter3 produces almost an image but without interpolation.
If I understand your question correctly you can use contour(X,Y,Z)
EDIT: You can use imagesc with a matrix that you make yourself. So if your x and y values are in a reasonable range you can just start with:
I = zeros(max(x), max(y));
for d = 1: length(x),
I(x(d),y(d)) = z(d);
end
imagesc(I);