如何在Matlab中使用3D直方图标记数据索引

时间:2014-06-27 14:29:31

标签: matlab histogram

我有一组数据点(大约20000)及其x,y值,我想删除与其他点不太接近的点。我尝试通过“数字化”来实现这一目标。我认为在Matlab中实现它的最接近的方法是3D直方图,所以我可以删除低计数箱中的点。我使用hist3(),但问题是我无法获得标记为计数的点的索引(如输出' ind'来自histc())。我能想到的唯一方法是嵌套for循环,这是我想要尝试的最后一件事。有什么方法可以标记点数指数或任何其他方法来做到这一点?

由于


我觉得我需要澄清一下 我有来自@rayryeng

生成的数据的直方图

有些垃圾箱有N = 0或N = 1所以我想删除这些垃圾箱中的数据。 对于histc(),有一种输出形式[bincounts,ind] = histc(),其中ind返回数据所属的bin数。所以我可以找到小于/等于或大于1的区间索引,然后找到特定区间中的数据。我可以为2D输入做类似的事情吗?

再次感谢

1 个答案:

答案 0 :(得分:0)

hist3应该能够为您完成此任务。我不太清楚问题出在哪里。您可以这样致电hist3

[N,C] = hist3(X);

这会自动将数据集划分为10 x 10网格的等间距容器。您可以通过执行以下操作来覆盖此行为:

[N,C] = hist3(X, NBINS);

NBINS是一个2元素数组,其中第一个元素告诉您垂直方向需要多少个分区,第二个元素是您想要水平分区的分区数。

N将告诉您网格的每个位置有多少元素,C将为您提供1 x 2单元格数组,其中单元格数组的第一个元素为您提供{{1 bin的每个中心的坐标,而单元格数组的第二个元素为你提供bin的每个中心的X坐标。

明确地说,如果我们有一个10 x 10网格,Y将包含一个双元素单元格数组,其中每个元素的长度为10个元素。对于C中找到的中心的每个X坐标,我们将在C{1}中有10个与{bin}中心相关的Y坐标。这意味着前10个bin中心位于C{2},然后接下来的10个bin中心位于:C{1}(1), C{2}(1), C{1}(1), C{2}(2), C{1}(1), C{2}(3), ..., C{1}(1), C{2}(10)

作为一个简单的例子,让我们在x轴上的C{1}(2), C{2}(1), C{1}(2), C{2}(2), C{1}(2), C{2}(3), ..., C{1}(1), C{2}(10)和y轴上的[0,1]之间的网格上执行此操作。我要生成100个2D点。我们还将图像水平分解为10个区域,垂直分割10个区域(默认为[0,1])。

hist3

我们得到:

rng(100); %// Set seed for reproducibility
A = rand(100,2);
[N,C] = hist3(A);
disp(N);
celldisp(C);

这告诉我们位于点分布左上角的第一个网格只有1个值。之后的下一个网格有2个垃圾箱登录,依此类推。我们还为N = 1 2 0 1 2 0 1 0 1 1 0 1 1 1 1 1 0 0 2 5 0 4 1 1 1 1 1 4 0 1 2 0 3 2 2 1 1 0 2 1 0 0 0 0 1 1 1 0 0 1 1 1 1 2 1 1 0 2 0 1 1 0 2 1 2 0 3 1 1 1 0 1 0 0 0 1 1 0 0 1 1 0 1 2 3 3 0 0 0 2 0 2 1 1 0 1 0 3 0 1 C{1} = Columns 1 through 7 0.0541 0.1528 0.2516 0.3503 0.4491 0.5478 0.6466 Columns 8 through 10 0.7453 0.8440 0.9428 C{2} = Columns 1 through 7 0.0513 0.1510 0.2508 0.3505 0.4503 0.5500 0.6498 Columns 8 through 10 0.7495 0.8493 0.9491 中显示的每个箱子设置了箱柜中心。请记住,我们有10 x 10个可能的bin中心。如果我们想要使用bin位置显示我们的数据,我们可以这样做:

C

我们得到:

enter image description here

红色星形表示bin中心,而蓝色星形表示网格中的数据点。因为我们的原点位于我们绘图的左下角,但[X,Y] = meshgrid(C{1},C{2}); plot(A(:,1), A(:,2), 'b*', X(:), Y(:), 'r*'); grid; 矩阵的原点位于左上角一角(即分解的第一个bin位于左上角)在我们的数据中,它位于左下角),我们需要将N旋转90度逆时针,以便每个矩阵的原点彼此一致,并且同意情节。就这样:

N

从图片中可以看出,这与我们在(轮换)Nrot = rot90(N); disp(Nrot); Nrot = 1 5 1 1 1 1 1 1 2 1 1 2 0 2 0 0 1 0 0 0 0 0 4 0 0 2 1 0 0 3 1 0 1 1 1 0 3 1 0 0 0 1 1 1 1 1 0 1 3 1 2 1 1 2 1 1 2 0 3 0 1 1 1 2 0 2 1 0 2 1 0 1 1 3 0 1 2 0 1 1 2 1 4 0 0 1 0 1 0 2 1 0 0 2 0 1 1 0 1 0 矩阵以及bin中心N中看到的内容一致。使用C(或N如果你的约定正确),你现在可以找出从你的点数组中消除的点数。在Nrot内成员资格较低的任何点,您会找到与N中的网格位置相关联的最靠近该中心的点并删除它们。

例如,假设第一行,第二列(旋转结果)中的bin是您要过滤掉的bin。这相当于N。我们也知道我们需要过滤5个点,因为它们属于这个bin中心。因此:

(C{1}(2), C{2}(10))

我们按升序对距离进行排序,然后确定距离此bin中心的numPointsToRemove = N(2,10); %//or Nrot(1,2); %// Computes Euclidean distance between this bin centre with every point dists = sqrt(sum(bsxfun(@minus, A, [C{1}(2) C{2}(10)]).^2, 2)); %// Find the numPointsToRemove closest points to the bin centre and remove [~,ind] = sort(dists); A(ind(1:numPointsToRemove,:)) = []; 最近点。因此,我们将它们从数据矩阵中删除。


如果您想要移除那些包含numPointsToRemove0计数器的区域,我们可以找到这些位置,然后运行1循环并相应地进行过滤。但是,任何具有for的容器意味着我们甚至不需要运行并过滤任何内容,因为没有点映射到那里!您确实需要过滤掉在箱中只有 1 的值。换句话说:

0

如您所见,这与上述过程类似。由于我们希望过滤出只有1个分配给bin的区域,我们只需要找到最小距离。请记住,我们不需要处理任何计数为0的容器,因此我们可以跳过这些容器。