How to replace values of a vector based on the values of another vector?

I have two vectors that together create a cartesian grid, such as this.
xmin = 0;
xmax = 500;
ymin = -200;
ymax = 200;
cell_size = 5;
x_cell(1) = xmin;
y_cell(1) = ymin;
for i = 1:2000
x_cell(i + 1) = xmin + cell_size * i;
if x_cell(i + 1) >= xmax
no_of_x_cells = i;
break
end
end
for i = 1:2000
y_cell(i + 1) = ymin + cell_size * i;
if y_cell(i + 1) >= ymax
no_of_y_cells = i;
break
end
end
r_vector = zeros(no_of_x_cells, no_of_y_cells);
I have another vector (I will call it "A" here) that includes x coordinates, y coordinates and arbitrary values (r). (I have attached the csv file that contains the data.)
Now, I want to map each arbitrary value (r) to the respective cell in my grid. So, for example, arbitrary value of the second element of A (which is 64.8436) will be included in (1,1) position of r_vector. And the arbitrary value of the 25th element of A (which is 5.7553) will be included in (18,1) position of r_vector. (Because x coordinate of A is 85.4922 and that belongs in 85-90 range of the x-grid, and y coordinate is -1.6285, which belongs in -5~0 range in y-grid. And so on.
Values that are not assigned will remain zero in r_vector, and if there are two values within the same cell, only the maximum value should be inserted.
I'm sorry if this is not descriptive enough or if it is too much to ask here. I've been struggling with this for a while now but I really cannot wrap my head around a possible approach. Any help or advice is appreciated. Thank you in advance!
(I'm also not sure about which tags to include here, so apologies)

 Accepted Answer

Take a look at the histcounts2 function. From your description what I think what you want are the 4th and 5th outputs.

5 Comments

Thanks a lot for the response! I've been reading the documentation on histcounts2 since your reply. But I'm not sure how it fits here. Because I thought coordinates in vector A have to be checked/comapred with the x_cell and y_cell values to identify the right position in r_vector, right?
Sorry if I'm mistaken here.
So let me see if I understand what you're trying to do with a smaller set of data. I think I missed one step from your original description and so histcounts2 will have a role to play but it won't be the end of the job. First let's make some grid vectors.
gridX = 0:0.25:1;
gridY = gridX;
Now some sample data that I'll show in a table array:
rng default
x = rand(10, 1);
y = rand(10, 1);
z = randi(10, 10, 1);
sampleData = table(x, y, z)
sampleData = 10×3 table
x y z _______ _______ __ 0.81472 0.15761 7 0.90579 0.97059 1 0.12699 0.95717 9 0.91338 0.48538 10 0.63236 0.80028 7 0.09754 0.14189 8 0.2785 0.42176 8 0.54688 0.91574 4 0.95751 0.79221 7 0.96489 0.95949 2
Here's where the data is. Note that these are the row indices into the sampleData table not the corresponding z values.
ax = axes;
text(x, y, string(1:10));
xline(gridX, 'r') % R2021a supports making several lines at once with {x,y}line
yline(gridY, 'r')
xticks(gridX)
yticks(gridY)
ax.YDir = 'reverse'; % Put y = 0 at the top
So for the cell between x = 0.5 and x = 0.75 and y = 0.75 and y = 1 you want to find which of z(5) and z(8) is largest and use that as the value for element (4, 3) of the final results matrix? Since z(5) is 7 and z(8) is 4 you'd want that value to be 7? That element is (4, 3) not (1, 3) because I flipped the Y axis to put the point x = 0, y = 0 at the top. In that case let's bin the data and determine to which bin each point belongs.
[~, ~, ~, binX, binY] = histcounts2(x, y, gridX, gridY);
sampleData.binX = binX;
sampleData.binY = binY
sampleData = 10×5 table
x y z binX binY _______ _______ __ ____ ____ 0.81472 0.15761 7 4 1 0.90579 0.97059 1 4 4 0.12699 0.95717 9 1 4 0.91338 0.48538 10 4 2 0.63236 0.80028 7 3 4 0.09754 0.14189 8 1 1 0.2785 0.42176 8 2 2 0.54688 0.91574 4 3 4 0.95751 0.79221 7 4 4 0.96489 0.95949 2 4 4
The z data in row 5 of the sampleData table belongs to x bin 3 and y bin 4. Remember the y bins are the rows and the x bins the columns.
Let's use the x and y bin data from histcounts2 to accumulate the z data. Since the bin values are integers we can use accumarray, treating the bin values as the row and column indices. I want to use this to make a 4-by-4 matrix (since we have 5 edges which gives us 4 bins in each direction) and I want to accumulate the z data using the max function.
accumarray([binY, binX], z, [4 4], @max)
ans = 4×4
8 0 0 7 0 8 0 10 0 0 0 0 9 0 7 7
Since this is a small example most of the bins contain no elements of the data or maybe one element, but it generalizes to larger data sets.
I'm not sure if I fully understood you but your method seemed to work! I implemented it as follows. However, the data is put in to the wrong bins :( I don't know exactly how to explain this - but the they were put in the wrong side of the grid. Basically, the x coordinates were correct but y coordinates were reversed.
I use imagesc to display the data as follows, hoping that would make it easier to convey what I'm trying to explain.
My code so far: (vector data that I'm using are the same ones from the attached csv file, btw)
xmin = 0;
xmax = 500;
ymin = -200;
ymax = 200;
cell_size = 5;
x_cell(1) = xmin;
y_cell(1) = ymin;
for i = 1:2000
x_cell(i + 1) = xmin + cell_size * i;
if x_cell(i + 1) >= xmax
no_of_x_cells = i;
break
end
end
for i = 1:2000
y_cell(i + 1) = ymin + cell_size * i;
if y_cell(i + 1) >= ymax
no_of_y_cells = i;
break
end
end
p = csvread('sample_data_matlab.csv');
x1 = p(:, 1);
y1 = p(:, 2);
r1 = p(:, 3);
[~, ~, ~, binX, binY] = histcounts2(x1, y1, x_cell', y_cell');
a = accumarray([binY, binX], r1, [81 100], @max);
Here is what I get and basically what I want to achieve.
I', sure this is a silly question but I couldn't really understand the approach. I'm still working on it and if you can think of a reason, I'd be super grateful!
I'm not sure how to explain this and probably that is the problem here, my apologies. Anyway, Thank you so much for your responses and advice! I have moved forward with my problem thanks to your input!
Your Y axis has the smallest values at the top and your y_cell variable is in increasing order. So the first row of bins (in the matrix) corresponds to the top of your plot. Is that what you expected? Or were you expecting the first row of bins to correspond to the bottom of your plot?
The latter. Basically the y axis has to be reversed. I didn't use the part:
ax.YDir = 'reverse';
But I was hoping that the bins will correspond to the bottom part - which is the negative side - automatically.

Sign in to comment.

More Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Asked:

on 11 Mar 2021

Commented:

on 15 Mar 2021

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!