Random sampling from gridded data: How to implement this in Matlab? - matlab

I have a 200x200 gridded data points. I want to randomly pick 15 grid points from that grid and replace the values in those grids with values selected from a known distribution shown below. All 15 grid points are assigned random values from the given distribution.
The given distribution is:
Given Distribution
314.52
1232.8
559.93
1541.4
264.2
1170.5
500.97
551.83
842.16
357.3
751.34
583.64
782.54
537.28
210.58
805.27
402.29
872.77
507.83
1595.1
The given distribution is made up from 20 values, which are part of those gridded data points. These 20 grid points are fixed i.e. they must not be part of randomly picking 15 points. The coordinates of these 20 points, which are fixed and should not be part of random picking, are:
x 27 180 154 183 124 146 16 184 138 122 192 39 194 129 115 33 47 65 1 93
y 182 81 52 24 168 11 90 153 133 79 183 25 63 107 161 14 65 2 124 79
Can someone help with how to implement this problem in Matlab?

Building off of my answer to your simpler question, here is a solution for how you can choose 15 random integer points (i.e. subscripted indices into your 200-by-200 matrix) and assign random values drawn from your set of values given above:
mat = [...]; %# Your 200-by-200 matrix
x = [...]; %# Your 20 x coordinates given above
y = [...]; %# Your 20 y coordinates given above
data = [...]; %# Your 20 data values given above
fixedPoints = [x(:) y(:)]; %# Your 20 points in one 20-by-2 matrix
randomPoints = randi(200,[15 2]); %# A 15-by-2 matrix of random integers
isRepeated = ismember(randomPoints,fixedPoints,'rows'); %# Find repeated sets of
%# coordinates
while any(isRepeated)
randomPoints(isRepeated,:) = randi(200,[sum(isRepeated) 2]); %# Create new
%# coordinates
isRepeated(isRepeated) = ismember(randomPoints(isRepeated,:),...
fixedPoints,'rows'); %# Check the new
%# coordinates
end
newValueIndex = randi(20,[1 15]); %# Select 15 random indices into data
linearIndex = sub2ind([200 200],randomPoints(:,1),...
randomPoints(:,2)); %# Get a linear index into mat
mat(linearIndex) = data(newValueIndex); %# Update the 15 points
In the above code I'm assuming that the x coordinates correspond to row indices and the y coordinates correspond to column indices into mat. If it's actually the other way around, swap the second and third inputs to the function SUB2IND.

I think yoda already gave the basic idea. Call randi twice to get the grid coordinate to replace, and then replace it with the appropriate value. Do that 15 times.

Related

Matlab - finding the values in a vector making a neighborhood chain

I have a vector that has values, say a=[10 20 42 90] and what I am trying to do is to find the neighbors in the range of 30 and replace these values with their means. For example, for the a vector, the value of 20 is a neighbor of 10. Additionally, 42 is also a neighbor of 10 through 20, because it is a neighbor's neighbor but 90 is not a neighboring value and it is not reachable from 10 with a neighborhood size of 30.
So I want to replace all 10, 20 and 42 with their means and obtain the vector a=[24 90].
If a=[10 20 42 66 155], then the resulting vector would be a=[34.5 155].
How do I achieve that?
a=[10 20 42 66 155]; % sample data
r = 30; % sample range
a = accumarray(cumsum([r+1 abs(diff(a))]>r).',a,[],#mean).';
Ungolfed and commented version:
a=[10 20 42 66 155]; % sample data
r = 30; % range
% difference between subsequent groupmembers. First difference is set to be higher than r
d = [r+1 abs(diff(a))];
% each group one label
L = cumsum(d>r);
% calculate mean of each group
a = accumarray(L.',a,[],#mean).';

3D histogram and conditional coloring

I have a series of ordered points (X, Y, Z) and I want to plot a 3D histogram, any suggestions?
I'm trying to do it by this tutorial http://www.mathworks.com/help/stats/hist3.html , but points are random here and presented as a function. My example is easier, since i already know the points.
Furthermore, depending on the number value of Z coordinate, i'd like to colour it differently. E.g. Max value - green, min value - red. Similar as in this case Conditional coloring of histogram graph in MATLAB, only in 3D.
So, if I have a series of points:
X = [32 64 32 12 56 76 65]
Y = [160 80 70 48 90 80 70]
Z = [80 70 90 20 45 60 12]
Can you help me with the code for 3D histogram with conditional coloring?
So far the code looks like this:
X = [32 64 32 12 56 76 65];
Y= [160 80 70 48 90 80 70];
Z= [80 70 90 20 45 60 12];
A = full( sparse(X',Y',Z'));
figure;
h = bar3(A); % get handle to graphics
for k=1:numel(h),
z=get(h(k),'ZData'); % old data - need for its NaN pattern
nn = isnan(z);
nz = kron( A(:,k),ones(6,4) ); % map color to height 6 faces per data point
nz(nn) = NaN; % used saved NaN pattern for transparent faces
set(h(k),'CData', nz); % set the new colors
end
colorbar;
Now I just have to clear the lines and design the chart to make it look useful. But how would it be possible to make a bar3 without the entire mesh on 0 level?
Based on this answer, all you need to do is rearrange your data to match the Z format of that answer. After than you might need to remove edgelines and possibly clear the zero height bars.
% Step 1: rearrange your data
X = [32 64 32 12 56 76 65];
Y= [160 80 70 48 90 80 70];
Z= [80 70 90 20 45 60 12];
A = full( sparse(X',Y',Z'));
% Step 2: Use the code from the link to plot the 3D histogram
figure;
h = bar3(A); % get handle to graphics
set(h,'edgecolor','none'); % Hopefully this will remove the lines (from https://www.mathworks.com/matlabcentral/newsreader/view_thread/281581)
for k=1:numel(h),
z=get(h(k),'ZData'); % old data - need for its NaN pattern
nn = isnan(z);
nz = kron( A(:,k),ones(6,4) ); % map color to height 6 faces per data point
nz(nn) = NaN; % used saved NaN pattern for transparent faces
nz(nz==0) = NaN; % This bit makes all the zero height bars have no colour
set(h(k),'CData', nz); % set the new colors. Note in later versions you can do h(k).CData = nz
end
colorbar;

How to define matrix values as a index in matlab?

I have 1788x3 double matrix.
My goal is split first and seconds columns values as a coordinates and create 256*256 matrix. Missing values will be zero.
That is the part of my matrix:
For example in 256*256 matrix (161,37) coordinates value will be 0.347365914411139
161 37 0.347365914411139
162 38 0.414350944291199
160 38 -0.904597803215328
165 35 -0.853613950415835
163 38 -0.926329070526244
166 35 -1.37361928823183
168 37 0.661707825299905
Looking forward your answers.
Regards;
The easiest, but not necessarily most efficient way to do this would be using a loop, i.e.
% if m = you 1788x3 data
x = sparse(256,256) %// x = zeros(256); % //use either of these
for nn = 1:size(m,1)
x(m(nn,1),m(nn,2)) = m(nn,3);
end

How to sample a plot in Matlab?

The plot in MATLAB looks like this:
The code to generate this is very simple:
y = [0 18 450];
x = [0 5.3 6.575];
plot(x,y);
How could I know the values of 119 equally spaced discrete points on this plot?
In simple MATLAB plots, the points are connected together by simple linear interpolation. Simply put, a straight line is drawn between each pair of points. You can't physically get these points from the graph other than those you used to plot the points (at least not easily...).
If you however do desire 119 points at equally spaced intervals that would theoretically be obtained from the above set of 4 points, you can use the interp1 function to do so:
y = [0 18 450];
x = [0 5.3 6.575]
yy = interp1(x, y, linspace(min(x),max(x),119), 'linear');
interp1 performs linear (note the 'linear' flag at the end...) interpolation given a set of key points defined by x and y points and a set of x points to use to interpolate between the key x points to generate the interpolated y points stored in yy. linspace in this case generates a linearly increasing array from the smallest value in x to the largest value in x with 119 of these points.
Here's a running example with your data:
>> format compact;
>> y = [0 18 450];
>> x = [0 5.3 6.575];
>> yy = interp1(x, y, linspace(min(x),max(x),119), 'linear');
>> yy
yy =
Columns 1 through 8
0 0.1892 0.3785 0.5677 0.7570 0.9462 1.1354 1.3247
Columns 9 through 16
1.5139 1.7031 1.8924 2.0816 2.2709 2.4601 2.6493 2.8386
Columns 17 through 24
3.0278 3.2171 3.4063 3.5955 3.7848 3.9740 4.1633 4.3525
Columns 25 through 32
4.5417 4.7310 4.9202 5.1094 5.2987 5.4879 5.6772 5.8664
Columns 33 through 40
6.0556 6.2449 6.4341 6.6234 6.8126 7.0018 7.1911 7.3803
Columns 41 through 48
7.5696 7.7588 7.9480 8.1373 8.3265 8.5157 8.7050 8.8942
Columns 49 through 56
9.0835 9.2727 9.4619 9.6512 9.8404 10.0297 10.2189 10.4081
Columns 57 through 64
10.5974 10.7866 10.9759 11.1651 11.3543 11.5436 11.7328 11.9220
Columns 65 through 72
12.1113 12.3005 12.4898 12.6790 12.8682 13.0575 13.2467 13.4360
Columns 73 through 80
13.6252 13.8144 14.0037 14.1929 14.3822 14.5714 14.7606 14.9499
Columns 81 through 88
15.1391 15.3283 15.5176 15.7068 15.8961 16.0853 16.2745 16.4638
Columns 89 through 96
16.6530 16.8423 17.0315 17.2207 17.4100 17.5992 17.7885 17.9777
Columns 97 through 104
34.6540 53.5334 72.4128 91.2921 110.1715 129.0508 147.9302 166.8096
Columns 105 through 112
185.6889 204.5683 223.4477 242.3270 261.2064 280.0857 298.9651 317.8445
Columns 113 through 119
336.7238 355.6032 374.4826 393.3619 412.2413 431.1206 450.0000

How to compare the pairs of coordinates most efficiently without using nested loops in Matlab?

If I have 20 pairs of coordinates, whose x and y values are say :
x y
27 182
180 81
154 52
183 24
124 168
146 11
16 90
184 153
138 133
122 79
192 183
39 25
194 63
129 107
115 161
33 14
47 65
65 2
1 124
93 79
Now if I randomly generate 15 pairs of coordinates (x,y) and want to compare with these 20 pairs of coordinates given above, how can I do that most efficiently without nested loops?
If you're trying to see if any of your 15 randomly generated coordinate pairs are equal to any of your 20 original coordinate pairs, an easy solution is to use the function ISMEMBER like so:
oldPts = [...]; %# A 20-by-2 matrix with x values in column 1
%# and y values in column 2
newPts = randi(200,[15 2]); %# Create a 15-by-2 matrix of random
%# values from 1 to 200
isRepeated = ismember(newPts,oldPts,'rows');
And isRepeated will be a 15-by-1 logical array with ones where a row of newPts exists in oldPts and zeroes otherwise.
If your coordinates are 1) actually integers and 2) their span is reasonable (otherwise use sparse matrix), I'll utilize a simple truth table. Like
x_0= [27 180 ...
y_0= [182 81 ...
s= [200 200]; %# span of coordinates
T= false(s);
T(sub2ind(s, x_0, y_0))= true;
%# now obtain some other coordinates
x_1= [...
y_1= [...
%# and common coordinates of (x_0, y_0) and (x_1, y_1) are just
T(sub2ind(s, x_1, y_1))
If your original twenty points aren't going to change, you'd get better efficiency if you sorted them O(n log n); then you could see if each random point was in the list with a O(log n) search.
If your "original" points list changes (insertions / deletions), you could get equivalent performance with a binary tree.
BUT: If the number of points you're working with is really as low as in your question, your double loop might just be the fastest method! Algorithms with low Big-O curves will be faster as the amount of data gets really big, but it's often at the cost of a one-time slowdown (in your case, the sort) - and with only 15x20 data points... There won't be a human-perceptible difference; you might see one if you're timing it on your system clock. Or you might not.
Hope this helps!