Matlab 在逻辑向量中查找“真”簇的位置

Matlab 在逻辑向量中查找“真”簇的位置,matlab,Matlab,我有以下逻辑向量: vect1 = [0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 1 1 0 0 0 1] 我想找到这个向量中的所有1值集群,以及它们的开始和结束索引。对于输出,我希望能够提出如下内容: 5 8 13 15 18 19 23 23 其中,第一个数字是每个集群的起始索引,第二个数字是每个集群的结束索引 编辑:我能够用Shai的答案的修改版本来实现这一点: pv = [vect1 0]; sv = [0 pv(1:(end-1))]; ev = [pv(2

我有以下逻辑向量:

vect1 = [0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 1 1 0 0 0 1]
我想找到这个向量中的所有1值集群,以及它们的开始和结束索引。对于输出,我希望能够提出如下内容:

5 8
13 15
18 19
23 23
其中,第一个数字是每个集群的起始索引,第二个数字是每个集群的结束索引

编辑:我能够用Shai的答案的修改版本来实现这一点:

pv = [vect1 0];
sv = [0 pv(1:(end-1))];
ev = [pv(2:end) 0];
starting = find( pv - sv == 1 )
ending = find( pv - ev == 1 )

要处理最后一个1,用零填充向量会更简单:

pv = [vect1 0];
sv = [0 pv];
ev = [pv(2:end) 0];
starting = find( pv - sv == 1 );
ending = find( pv - sv == -1 );

要处理最后一个1,用零填充向量会更简单:

pv = [vect1 0];
sv = [0 pv];
ev = [pv(2:end) 0];
starting = find( pv - sv == 1 );
ending = find( pv - sv == -1 );

这个问题几乎是重复的。从这里改编我的答案:

vect1 = [0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 1 1 0 0 0 1];
v1 = (vect1(:)==1);
d = diff(v1);
output = [find([v1(1);d]==1) find([d;-v1(end)]==-1)]
返回

output =

     5     8
    13    15
    18    19
    23    23
要查找的两个调用可以使用

[output,~] = find([[v1(1);d] [-d;v1(end)]]==1);
output = reshape(output,[length(output)/2 2]);

这个问题几乎是重复的。从这里改编我的答案:

vect1 = [0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 1 1 0 0 0 1];
v1 = (vect1(:)==1);
d = diff(v1);
output = [find([v1(1);d]==1) find([d;-v1(end)]==-1)]
返回

output =

     5     8
    13    15
    18    19
    23    23
要查找的两个调用可以使用

[output,~] = find([[v1(1);d] [-d;v1(end)]]==1);
output = reshape(output,[length(output)/2 2]);

这是我能想到的最简单的一行

out =  [find(diff([0 vect1 0])==1); find(diff([0 vect1 0])==-1)-1]'

这是我能想到的最简单的一行

out =  [find(diff([0 vect1 0])==1); find(diff([0 vect1 0])==-1)-1]'

Matlab文件交换中有一个运行长度编码函数,我用它来解决这类问题。此解决方案(即rle函数)的好处在于,它可以发现重复的块,而无需事先知道哪些值将重复

encoded = rle(vect1);
summed = cumsum(encoded{2});
isOne = encoded{1}==1;
[summed(isOne)-encoded{2}(isOne)+1;  summed(isOne)]'
见:

或者稍微快一点

blockEnds = [ find(vect1(1:end-1) ~= vect1(2:end)) length(vect1) ];
blockStarts = [ 1 blockEnds(1:end-1)+1];
isOne = vect1(blockEnds)==1;
[blockStarts(isOne); blockEnds(isOne)]'

Matlab文件交换中有一个运行长度编码函数,我用它来解决这类问题。此解决方案(即rle函数)的好处在于,它可以发现重复的块,而无需事先知道哪些值将重复

encoded = rle(vect1);
summed = cumsum(encoded{2});
isOne = encoded{1}==1;
[summed(isOne)-encoded{2}(isOne)+1;  summed(isOne)]'
见:

或者稍微快一点

blockEnds = [ find(vect1(1:end-1) ~= vect1(2:end)) length(vect1) ];
blockStarts = [ 1 blockEnds(1:end-1)+1];
isOne = vect1(blockEnds)==1;
[blockStarts(isOne); blockEnds(isOne)]'

代码给了我一个矩阵,尺寸必须一致。错误,所以我做了一些修改并将它们发布在上面。请让我知道,如果你同意这些。代码给了我一个矩阵尺寸必须同意。错误,所以我做了一些修改并将它们发布在上面。如果你同意这些,请告诉我。谢谢你的回答!这也是可行的,但是Shai的解决方案要快得多,我需要多次运行这段代码??我只是测试了一下,实际上看不出有什么区别。在任何情况下,diff都应该更快地进行多核优化,等等,但对于简单的情况,最新版本中的JIT可能会做得很好。它必须足够聪明,以找出两个向量减法是相同的。谢谢你的回答!这也是可行的,但是Shai的解决方案要快得多,我需要多次运行这段代码??我只是测试了一下,实际上看不出有什么区别。在任何情况下,diff都应该更快地进行多核优化,等等,但对于简单的情况,最新版本中的JIT可能会做得很好。它一定很聪明,能找出两个向量减法是相同的。我的工作答案有什么问题吗?如果你的向量很大,使用diff会更有效率。有趣的是,我还没有测试过更大的向量,事实上我将使用它。我将测试这些,并会让你知道。再次感谢!我创建了一个包含100000个元素的向量vect1=randi[01],11000,然后在for循环中以1000次迭代运行这两个解决方案。更新后的答案执行时间为2.3秒;Shai在反复尝试中获得了1.6分。100000相当于我的向量大小。我还缺什么吗?再次感谢您使用与您的问题相同的输出矩阵的代码进行测试:2.1415和2.1419。这些东西依赖于版本、操作系统和硬件。您还必须正确计时,否则您测量的是错误的东西-必须在调用每个版本之间清除变量,并且您应该在计时之前通过调用代码进行预热。更重要的是:使用适合你并且你理解的代码。你能测试一下我在下面发布的版本的速度吗?它避免了在其他解决方案中进行的一些复制,只使用一个查找。我的工作答案有什么问题吗?如果你的向量很大,使用diff会更有效率。有趣的是,我还没有测试过更大的向量,事实上我将使用它。我将测试这些,并会让你知道。再次感谢!我创建了一个包含100000个元素的向量vect1=randi[01],11000,然后在for循环中以1000次迭代运行这两个解决方案。更新后的答案执行时间为2.3秒;Shai在反复尝试中获得了1.6分。100000相当于我的向量大小。我还缺什么吗?再次感谢您使用与您的问题相同的输出矩阵的代码进行测试:2.1415和2.1419。这些东西依赖于版本、操作系统和硬件。您还必须正确计时,否则您测量的是错误的东西-必须在调用每个版本之间清除变量,并且您应该在计时之前通过调用代码进行预热。更重要的是:使用适合你并且你理解的代码。你能测试一下速度吗 我的版本也贴在下面?它避免了在其他解决方案中进行的一些复制,并且只使用一个查找。