简体   繁体   English

Matlab:如何为多个点找到一个封闭的网格单元索引

[英]Matlab: how to find an enclosing grid cell index for multiple points

I am trying to allocate (x, y) points to the cells of a non-uniform rectangular grid. 我试图将(x,y)点分配给非均匀矩形网格的单元格。 Simply speaking, I have a grid defined as a sorted non-equidistant array 简单来说,我将网格定义为排序的非等距数组

xGrid = [x1, x2, x3, x4];

and an array of numbers x lying between x1 and x4 . 以及位于x1x4之间的数字x For each x , I want to find its position in xGrid , ie such i that 对于每个x ,我想在xGrid找到它的位置,即i那个

xGrid(i) <= xi <= xGrid(i+1)

Is there a better (faster/simpler) way to do it than arrayfun(@(x) find(xGrid <= x, 1, 'last'), x) ? 有没有比arrayfun(@(x) find(xGrid <= x, 1, 'last'), x)更好(更快/更简单)的方法arrayfun(@(x) find(xGrid <= x, 1, 'last'), x)

You are looking for the second output of histc : 您正在寻找histc的第二个输出:

[~,where] = histc(x, xGrid)

This returns the array where such that xGrid(where(i)) <= x(i) < xGrid(where(i)+1) holds. 这将返回数组where xGrid(where(i)) <= x(i) < xGrid(where(i)+1)成立。

Example: 例:

xGrid = [2,4,6,8,10];
x = [3,5,6,9,11];
[~,where] = histc(x, xGrid)

Yields the following output: 产生以下输出:

where =
     1     2     3     4     0

If you want xGrid(where(i)) < x(i) <= xGrid(where(i)+1) , you need to do some trickery of negating the values: 如果你想要xGrid(where(i)) < x(i) <= xGrid(where(i)+1) ,你需要做一些否定值的xGrid(where(i)) < x(i) <= xGrid(where(i)+1)

[~,where] = histc(-x,-flip(xGrid));
where(where~=0) = numel(xGrid)-where(where~=0)

This yields: 这会产生:

where =
     1     2     2     4     0

Because x(3)==6 is now counted for the second interval (4,6] instead of [6,8) as before. 因为x(3)==6现在计算第二个间隔(4,6]而不是之前的[6,8) (4,6]

If x is a column this might help 如果x是一列,这可能会有所帮助

xg1=meshgrid(xGrid,1:length(x));
xg2=ndgrid(x,1:length(xGrid));
[~,I]=min(floor(abs(xg1-xg2)),[],2);

or a single line implementation 或单行实现

[~,I]=min(floor(abs(meshgrid(xGrid,1:length(x))-ndgrid(x,1:length(xGrid)))),[],2);

Example: xGrid=[1 2 3 4 5], x=[2.5; 1.3; 1.7; 4.8; 3.3] 示例: xGrid=[1 2 3 4 5], x=[2.5; 1.3; 1.7; 4.8; 3.3] xGrid=[1 2 3 4 5], x=[2.5; 1.3; 1.7; 4.8; 3.3]

Result: 结果:

I =
     2
     1
     1
     4
     3

See if this works for you - 看看这是否适合你 -

matches  = bsxfun(@le,xGrid(1:end-1),x(:)) & bsxfun(@ge,xGrid(2:end),x(:))
[valid,pos] = max(cumsum(matches,2),[],2)
pos = pos.*(valid~=0)

Sample run - 样品运行 -

xGrid =
     5     2     1     6     8     9     2     1     6
x =
     3     7    14
pos =
     8
     4
     0

Explanation on the sample run - 关于样本运行的说明 -

First element of x, 3 occurs last between ...1 6 with the criteria of xGrid(i) <= xi <= xGrid(i+1) at the backend of xGrid and that 1 is at the eight position, so the first element of the output pos is 8 . x的第一元件, 3发生最后之间...1 6用的标准xGrid(i) <= xi <= xGrid(i+1)在后端xGrid1是在八个位置,所以第输出pos元素是8 This continues for the second element 7 , which is found between 6 and 8 and that 6 is at the fourth place in xGrid , so the second element of the output is 4 . 这对于第二元素7继续,其在6 and 8之间找到并且6xGrid中处于第四位置,因此输出的第二元素是4 For the third element 14 which doesn't find any neighbours to satisfy the criteria xGrid(i) <= xi <= xGrid(i+1) and is therefore outputted as 0 . 对于没有找到任何邻居的第三元素14满足标准xGrid(i) <= xi <= xGrid(i+1)并因此输出为0

Using bsxfun for the comparisons and exploiting find -like capabilities of max 's second output: 使用bsxfun进行比较并利用max的第二个输出的bsxfun find的功能:

xGrid = [2 4 6 8]; %// example data
x = [3 6 5.5 10 -10]; %// example data
comp = bsxfun(@gt, xGrid(:), x(:).'); %'// see if "x" > "xGrid"
[~, result] = max(comp, [], 1); %// index of first "xGrid" that exceeds each "x"
result = result-1; %// subtract 1 to find the last "xGrid" that is <= "x"

This approach gives 0 for values of x that lie outside xGrid . 对于位于xGrid外部的x值,此方法为0 With the above example values, 使用上面的示例值,

result =
     1     3     2     0     0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM