我试图删除按顺序重复的行。我只有2个可能的值,分别为0和1.我有nXm,n表示可能的位数,m对我的问题不重要。我的目标是找到一个nX(m-a)的矩阵。行a具有按顺序包含重复项的属性。例如:
我的矩阵是:
A=[0 1 0 1 0 1;
0 0 0 1 1 1;
0 0 1 0 0 1;
0 1 0 0 1 0;
1 0 0 0 1 0]
我想删除行中有0个重复序列的行。在这个问题中,我们假设t是3.所以我想要矩阵:
B=[0 1 0 1 0 1;
0 0 1 0 0 1;
0 1 0 0 1 0]
第2行和第5行被删除。
我可能需要使用diff。
答案 0 :(得分:6)
因此,您要删除序列中至少包含A
个零的t
行。
一行怎么样?
B = A(~any(conv2(1,ones(1,t),2*A-1,'valid')==-t, 2),:);
如何运作:
A
转换为双极形式(2*A-1
)t
个(conv2(...)
)-t
~any(...))
。-t
的存在表示t
的相应行中A
个零的序列1}}。要删除至少包含t
的行的行,只需将-t
更改为t
:
B = A(~any(conv2(1,ones(1,t),2*A-1,'valid')==t, 2),:);
答案 1 :(得分:3)
使用字符串的方法怎么样?这肯定不如Luis Mendo直接使用数值数组的方法那么快,但它的思维方式有点突破。这种方法的基础是我认为A
的每一行都是唯一的字符串,我可以通过正则表达式搜索每个字符串中是否出现0字符串。
A=[0 1 0 1 0 1;
0 0 0 1 1 1;
0 0 1 0 0 1;
0 1 0 0 1 0;
1 0 0 0 1 0];
t = 3;
B = sprintfc('%s', char('0' + A));
ind = cellfun('isempty', regexp(B, repmat('0', [1 t])));
B(~ind) = [];
B = double(char(B) - '0');
我们得到:
B =
0 1 0 1 0 1
0 0 1 0 0 1
0 1 0 0 1 0
第1行:将矩阵A
的每一行转换为由0和1组成的字符串。每行成为单元阵列中的单元格。这使用未记录的函数sprintfc
来促进此单元阵列转换。
第2行:我使用regular expressions来查找t
长的0字符串的出现次数。我首先使用repmat
创建一个充满0且长度为t
的搜索字符串。之后,我确定此单元格数组中的每一行是否包含此字符序列(即000....
)。函数regexp
帮助我们执行正则表达式并返回单元格数组中每个单元格的任何匹配的位置。或者,您可以将函数strfind
用于更新版本的MATLAB以加速计算,但我选择了regexp
,以便该解决方案与大多数MATLAB版本兼容。
继续,regexp/strfind
的输出是元素的单元格数组,其中每个单元格报告我们找到特定字符串的位置。如果我们匹配,则输出中应至少有一个位置报告,因此我检查是否有任何匹配为空,这意味着这些是我们 don&#的行39; t想要删除。我想将其转换为logical
数组,以便从A
中删除行,因此这将包含cellfun
调用以确定空的单元格。因此,此行返回logical
数组,其中0表示删除此行,1表示我们不删除。
第3行:我从第2行获取logical
数组,然后反转,因为这是我们真正想要的。我们使用这个反转数组索引到单元格数组并删除这些字符串。
第4行:输出仍然是一个单元格数组,因此我将其转换回字符数组,最后返回数值数组。
答案 2 :(得分:3)
这是一种通用的方法,可以删除任何已经给出连续重复数量的行(不只是zero
。可以是任何数字)。
t = 3;
row_mask = ~any(all(~diff(reshape(im2col(A,[1 t],'sliding'),t,size(A,1),[]))),3);
out = A(row_mask,:)
示例运行
>> A
A =
0 1 0 1 0 1
0 0 1 5 5 5 %// consecutive 3 5's
0 0 1 0 0 1
0 1 0 0 1 0
1 1 1 0 0 1 %// consecutive 3 1's
>> out
out =
0 1 0 1 0 1
0 0 1 0 0 1
0 1 0 0 1 0