[英]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
. 以及位于
x1
和x4
之间的数字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)
成立。
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)
在后端xGrid
和1
是在八个位置,所以第输出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
之间找到并且6
在xGrid
中处于第四位置,因此输出的第二元素是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.