找到水平或垂直放置在矩阵中的向量

时间:2017-11-25 16:52:40

标签: matlab matrix vector match

我试图在一个大矩阵B中找到一个向量A
B可以包含多行和一列A,或多列和一行A

例如:

A = [56  55  53  52  53;
     49  45  44  45  47;
     33  30  31  34  35;
     34  34  27  24  26;
     44  48  45  35  24;
     56  57  57  53  39;
     62  62  62  60  55;
     62  61  61  54  47;
     49  47  42  40  32;
     47  42  44  45  40];

B = [34 27 24];

我需要一个返回row和col索引的函数,例如:
找到(A,B)→第4行,第2到第4列(对于给定的例子)。

怎么做?

3 个答案:

答案 0 :(得分:4)

我们可以typecast矩阵到char并使用strfind搜索矩阵:

%Horizontal search
A_str_h = typecast(A.','char');
B_str = typecast(B,'char');
charsize = numel(B_str)/numel(B);
pos_h = strfind(A_str_h,B_str)-1;
pos_h = pos_h(mod(pos_h,charsize)==0)/charsize+1;
[col_h row_h] = ind2sub(flip(size(A)),pos_h);
idx_h = col_h <= (size(A,2)-numel(B)+1);
row_h = row_h(idx_h);
col_h = col_h(idx_h);

%Vertical search
A_str_v = typecast(A,'char');
B_str = typecast(B,'char');
charsize = numel(B_str)/numel(B);
pos_v = strfind(A_str_v,B_str)-1;
pos_v = pos_v(mod(pos_v,charsize)==0)/charsize+1;
[row_v col_v] = ind2sub(size(A),pos_v);
idx_v = row_v <= (size(A,1)-numel(B)+1);
row_v = row_v(idx_v);
col_v = col_v(idx_v);

使用convn的另一种解决方案:

n = numel(B);
C = A == reshape(B,1,1,n);
mask_h = permute(eye(n),[3 2 1]);
mask_v = permute(eye(n),[1 3 2]);
[xh yh]=find(convn(C,mask_h,'valid')==n);
[xv yv]=find(convn(C,mask_v,'valid')==n);

[xh yh]表示水平匹配的起始位置,[xv yv]表示垂直匹配的起始位置。

以下是测试将A设置为[2750 * 1250]矩阵并为B设置不同大小的不同方法的结果:

Result of Benchmark

结果显示CONVN效率低于其他方法,不适用于大尺寸数组,STRFIND最适合所有数组大小。

*方法在Octave中进行测试。

答案 1 :(得分:2)

对于固定大小的B,您可以使用以下方法:

[row, col] = find(A(:, 1:end-2) == B(1) & ...
                  A(:, 2:end-1) == B(2) & ...
                  A(:, 3:end) == B(3))

这将返回row = 4col = 2,即B(1)A的位置。

有关详细信息,请参阅Find Array Elements That Meet a Condition

可以使用for循环将其扩展为可变大小向量B

Ah = true(size(A) - [0 length(B)-1]);
for i=1:length(B)
    Ah= Ah & A(:, i:end-length(B)+i) == B(i);
end
[row, col] = find(Ah);

这可以很容易地扩展,以便按以下方式查找B 水平和垂直的出现次数:

Ah = true(size(A) - [0 length(B)-1]);
Av = true(size(A) - [length(B)-1 0]);
for i=1:length(B)
    Ah= Ah & A(:, i:end-3+i) == B(i);
    Av= Av & A(i:end-3+i, :) == B(i);
end
[row_h, col_h] = find(Ah);
[row_v, col_v] = find(Av);

<强>基准

请注意,尽管如此我使用for循环这种方法比rahnema1的解决方案更快,特别是如果你只对水平(或垂直)匹配感兴趣。有关详细信息,请查看the benchmark

答案 2 :(得分:2)

rahnema1和m7913d

之间的基准

水平和垂直匹配

对于给定的示例( Small A ),使用df1 <- transform(df1, lepsp_updated = ifelse(is.na(lepsp_updated),lepsp, lepsp_updated)) 对rahnema1和m7913d的解决方案进行基准测试,并为{{1>}更大的<{1>} ),给出以下结果:

timeit

请注意,m7913d的解决方案速度提高了约50%。

水平(或垂直)仅匹配

如果您只对水平匹配感兴趣,可获得以下结果:

100^2

在这种情况下,m7913d的解决方案更加有利,速度提高了约100%。

完成基准代码

Method   | Small A    | Large A
--------------------------------
rahnema1 | 4.0416e-05 | 0.0187
m7913d   | 2.5242e-05 | 0.0129