从序列中过滤短长度的变化(MATLAB)

从序列中过滤短长度的变化(MATLAB),matlab,Matlab,标题有点含糊不清,但我不知道该怎么说。我得到的是一个相当长的数组,比如长度为10000的数组,其中包含值1、2和3。它们通常位于相同数字的长字符串中,例如 [1111111111122222222211111222222222233333332222] 数据表示某物的3种状态,即1、2和3。唯一可能的转换是12、23,而不是13 一般来说,字符串非常长,因此不太可能观察到类似[111121111]的情况,其中单个元素的字符串变为2,然后返回。然而,由于测量中的误差,这些东西确实出现了,我正试图

标题有点含糊不清,但我不知道该怎么说。我得到的是一个相当长的数组,比如长度为10000的数组,其中包含值1、2和3。它们通常位于相同数字的长字符串中,例如

[1111111111122222222211111222222222233333332222]
数据表示某物的3种状态,即1、2和3。唯一可能的转换是12、23,而不是13

一般来说,字符串非常长,因此不太可能观察到类似[111121111]的情况,其中单个元素的字符串变为2,然后返回。然而,由于测量中的误差,这些东西确实出现了,我正试图找到一种在MATLAB中过滤掉它们的方法。所以我要做的是删除所有元素,对于这些元素,连续相同元素的数量小于某个数字X。如果对于一般的X很难做到,那么X=1是一个很好的开始


就我个人而言,我不知道如何解决这个问题。我想象使用diff可以告诉你元素在哪里变化,当它们再次变化时,通过指示它们的索引,你可以找到序列的长度。然后,使用一些if条件,可以删除它们。这可能应该向后进行,因为数组的大小将发生变化。我仍在努力让这些东西发挥作用,但到目前为止还没有成功。也许有人能给我一个提示?

这可能是一种方法-

%%// Input string
a1 = '111111111112222222221111122222222221111133333332222'

th = 10 %%// Less than or equal to 10 consecutive oocurances shall be removed

str1 = num2str(a1=='1','%1d')

t1 = strfind(['0' str1 '0'],'01')' %%//'
t2 = strfind(['0' str1 '0'],'10')' %%//'
t3 = [t1 t2-1]
t4 = t3([t2-t1]<=th,:)

ind1 = true(size(a1))
for k=1:size(t4,1)
  ind1(t4(k,1):t4(k,2))=false;
end
out = a1(ind1) %%// Output string

方法1(使用
bsxfun
。效率低下。我建议使用第二种方法。1)

以下代码检测短期运行的开始。从您的问题中不清楚该怎么做(删除这些条目?用前面的值填充它们?)

请注意,不考虑最后一次运行。因此,在本例中,即使最后一次运行比
len
短,也不会检测到太短。如果还需要检测该运行,请将
ind
行更改为

ind = find([diff(x-'0') inf]~=0) + 1;
在这种情况下,

result =
    21    43

方法2(使用
diff
。比方法1更有效。)

将每个索引与前面的索引进行比较就足够了,而不是与上面的所有其他索引进行比较。此外,根据评论,短期运行需要替换为前面的值;如果短,还应检测最后一次运行:

%// Data
x = '1111111111122222222211111222222222233333332222'; %// data (string)
len = 5; %// runs of this length or shorter will be detected

%// Detect beginning of short runs
ind = find([diff(x-'0') inf]~=0) + 1;
starts = ind(diff(ind)<=len); %// index of beginning of short runs

%// Replace short runs with preceding value
ind = [ind numel(x)+1]; %// extend ind in case last run was detected as short
for k = find(diff(ind)<=len)
    x(ind(k):ind(k+1)-1) = x(ind(k)-1); %// replace
end
%//数据
x='11111111222222211111222222222233333332222';%//数据(字符串)
len=5;%//将检测到此长度或更短的管路
%//检测短期运行的开始
ind=find([diff(x-'0')inf]~=0)+1;

starts=ind(diff(ind)Hm,我不确定它是否真的有效。我尝试了th=1,a1='112111322333122',但输出中实际上没有任何变化。此外,我希望实际使用数组而不是字符串(就我而言,这是一个非常糟糕的术语字符串用法,我的意思是作为链,而不是实际意义,我道歉),但它当然很容易改变,正如演示代码中所评论的-
th=10%%//应删除少于10个连续的oocurance
,因此,如果您将
th=1
,什么都不会改变。如果将
a1
作为双数组,它不会有太大变化,只需使用
str1=num2str(a1==1,%1d'))
。这完全是我的错误。不过,对于该输入,th=2也不起作用……我在注释中犯了更多的错误。我在这里将char称为字符串。要返回双精度,只需减去
0
的ascii值或使用
-“0”
11111111 2333333会发生什么?它应该在X=1的情况。好的,但是你如何决定2是变成1还是3?始终是1?还是始终是前面的符号?是的,这是我肯定忘记添加的东西。符号应该被前面的符号替换。我正在寻找一些
bsxfun
方法!谢谢你的帮助!条目最好用上一个值,我确实忘记在第一点中提到。同时查看最后一个序列会很好,但它不是必需的。但是我必须亲自查看bsxfun,因为我还不完全理解。@user129412
bsxfun(@减号,ind.,ind)
只计算差值(
@减号
)在
ind
的所有值组合之间(当使用列向量
ind.
和行向量
ind
馈送时,
bsxfun
生成所有此类组合)但我现在遇到了一个问题。我在内存不足的情况下使用bsxfun时出错。请键入“帮助内存”以获取选项。这是用于长度为20000的输入字符串。@user129412是的,
bsxfun
在这种情况下尝试构建20000x2000矩阵,这会导致错误。对于如此大的大小,您可能需要求助于循环。@Diva呢卡尔的回答?
ind = find([diff(x-'0') inf]~=0) + 1;
result =
    21    43
%// Data
x = '1111111111122222222211111222222222233333332222'; %// data (string)
len = 5; %// runs of this length or shorter will be detected

%// Detect beginning of short runs
ind = find([diff(x-'0') inf]~=0) + 1;
starts = ind(diff(ind)<=len); %// index of beginning of short runs

%// Replace short runs with preceding value
ind = [ind numel(x)+1]; %// extend ind in case last run was detected as short
for k = find(diff(ind)<=len)
    x(ind(k):ind(k+1)-1) = x(ind(k)-1); %// replace
end