【问题标题】:Search for 1-D sequence in multidimensional array in Matlab在Matlab中搜索多维数组中的一维序列
【发布时间】:2015-01-19 14:51:55
【问题描述】:

我有一个 n 维数组,并且我在所有其他维度上的某个位置有一个沿一个维度的序列。我如何找到这个序列的位置?最好不要循环。

我使用matlab。我知道它应该在哪个维度,但序列不一定在那里。查找和 == 不起作用。我可以使用互相关创建一个 nd find 函数,但我猜这已经实现了,我只是不知道要调用什么函数。

示例:

ND = rand(10,10,10,10);
V = ND(randi(10),randi(10),randi(10),:);
[I1, I2, I3] = find(ND==V);

编辑:要找到的序列跨越了它所在的整个维度,我在最初的问题表述中没有提到这一点。 Knedlsepp 的解决方案正好解决了我遇到的问题,但 Luis 的解决方案解决了一个更普遍的问题,即序列不一定跨越整个维度。

【问题讨论】:

  • 您是否尝试过相关性?我想您可以将序列与矩阵相关联,并且具有最高 corr 的点(如果它完全等于 corr = 1)将是您想要的那个。这样,您将能够查看序列是否在不同的地方也重复。
  • 您是否已经知道您正在查看哪个维度(例如,在您给出的示例中,您知道要查看第三个维度吗?)
  • 是的,我知道尺寸
  • 有点跑题了,但你应该使用randi(10)而不是round(10*rand)。因为第一个将产生从 0 到 10 的整数。
  • 图案有没有可能没有出现一次?例如:ND = [1 2 1 2; 3 4 5 6]V = [1 2],沿第二个暗角搜索

标签: matlab multidimensional-array find


【解决方案1】:

由于有多种方法可以解释您的问题,我将澄清:此方法假定一维大小序列:numel(V) == size(ND, dimToSearch)。因此,对于 V = [1,2]ND = [1,2,1,2] 它不适用。如果您想要此功能,请使用 Luis Mendo 的答案,否则可能会更快。

这将是一个使用bsxfun的绝佳机会:

我们从一些示例数据开始:

ND = rand(10,10,10,10);
V = ND(3,2,:,3);

如果您没有给出正确维度的矢量V(在本例中为[1,1,10,1]),您可以通过以下方式对其进行整形:

dimToSearch = 3;
Vdims = ones(1, ndims(ND)); 
Vdims(dimToSearch) = numel(V);
V = reshape(V, Vdims);

现在我们生成一个存储匹配索引的单元格:

I = cell(1, ndims(ND));

此时我们计算ND 的大小,如果它沿维度dimToSearch 折叠(我们根据V 计算dimToSearch,因为此时它将具有正确的维度):

dimToSearch = find(size(V)>1);
collapsedDims = size(ND); 
collapsedDims(dimToSearch) = 1;

最后是我们真正寻找模式的部分:

[I{:}] = ind2sub(collapsedDims, find(all(bsxfun(@eq, ND, V), dimToSearch)));

这是通过以下方式完成的:bsxfun(@eq, ND, V) 将隐式 repmat 数组 V 因此它具有与 ND 相同的维度并进行相等比较。在此之后,我们检查all 以查看维度dimToSearch 中的所有条目是否相等。对findind2sub 的调用将为您的数据生成正确的索引。

【讨论】:

  • dim 可以用find(size(V)>1) 替换为通用的吗?
  • 一般我的数组有 n>3
  • 这真的有效吗?我正在尝试使用 ND = [1 2 1 4; 3 1 2 6], V = [1 2] 并遇到错误(可能我理解错误)
  • @Leo:你必须在那里使用ind2sub。给我一点时间。
  • @LuisMendo:让我再读一遍这个问题。我的印象是V 会以正确的方式给出 (V = [1;2])
【解决方案2】:

d 成为搜索的维度。我假设寻找的序列V 可能比size(ND,d) 短。所以这个序列可能会出现一次,不止一次,或者从不在每个维度上出现-d-“线程”。

以下代码使用num2cellND 重塑为一个单元格数组,以便每个维度-d-thread 位于不同的单元格中。然后将strfind 应用于每个单元格以确定与V 的匹配,结果是一个与ND 具有相同维度的单元格数组,但其中维度d 是一个单例。每个单元格的内容告诉d-dimension-positions 匹配项(如果有)。

感谢@knedlsepp 建议使用num2cell,这大大简化了代码。

ND = cat(3, [1 2 1 2; 3 4 5 6],[2 1 0 5; 0 0 1 2] ); %// example. 2x4x2
V = 1:2; %// sought pattern. It doesn't matter if it's a row, or a column, or...
d = 2; %// dimension along which to search for pattern V
result = cellfun(@(x) strfind(x(:).', V(:).'), num2cell(ND,d), 'UniformOutput', 0);

这给了

ND(:,:,1) =
     1     2     1     2
     3     4     5     6
ND(:,:,2) =
     2     1     0     5
     0     0     1     2

V =
     1     2

result{1,1,1} =
     1     3    %// V appears twice (at cols 1 and 3) in 1st row, 1st slice
result{2,1,1} =
     []         %// V doesn't appear in 2nd row, 1st slice
result{1,1,2} =
     []         %// V appears appear in 1st row, 2nd slice
result{2,1,2} =
     3          %// V appears once (at col 3) in 2nd row, 2nd slice

【讨论】:

  • 哦!我刚刚明白你对我的回答的评论是什么意思!我以为 OP 被赋予了一个大小为 numel(V) == size(ND, d)! 的模式
  • @knedlsepp 现在我知道您的回答在做什么,以及为什么可以如此简单地完成 :-) 好吧,我们将看看 OP 真正想要什么。这个问题确实不是很清楚
  • 在逐步了解您的解决方案以了解发生了什么之后,我认为您可以使用result = cellfun(@(x) strfind(x(:).', V(:).'), num2cell(ND,d), 'uni', 0) 进行简化
  • @knedlsepp 好一个!我总是忘记num2cell。在这种情况下,它简化了很多事情。我认为您应该将其作为单独的答案!或者将其添加到您的答案中,即
  • @Leo 是的,在这种情况下,knedlsepp 的答案可以满足您的需求。我已经编辑了我的答案以反映我对问题的解释。
【解决方案3】:

一种不太理想的方法:

    dims = size(ND);
    Vrep = repmat(V, [dims(1), dims(2), dims(3), 1]);
    ND_V_dist = sqrt(sum(abs(ND.^2-Vrep.^2), 4));
    iI = find(ND_V_dist==0);
    [I1, I2, I3] = ind2sub([dims(1), dims(2), dims(3)], iI);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-22
    • 1970-01-01
    • 2022-01-03
    • 2016-09-19
    • 2017-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多