在MATLAB分裂矢量 [英] Split vector in MATLAB

查看:173
本文介绍了在MATLAB分裂矢量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图分裂优雅的向量。例如,

  VEC = [1 2 3 4 5 6 7 8 9 10]

根据0和1的相同的长度,其中1的指示,其中该载体应拆分的的另一种载体 - 或者说切

 切= [0 0 0 1 0 0 0 0 1 0]

给予我们类似如下的电池输出:

  [1 2 3] [5 6 7 8] [10]


解决方案

解决方案code

您可以使用 cumsum &安培; accumarray 一个有效的解决方案 -

  //%用于accumarray使用创建ID /标签以后
ID = cumsum(切)+1//%面膜从对应于那些在裁剪切割和血管内皮细胞得到有效的值
面膜=切== 0//%使用屏蔽ID和VEC值终于搞定与accumarray输出
OUT = accumarray(ID(面罩)。,VEC(面罩)。[] @(X){X})


标杆

下面是一些性能参数上使用列出的三个最流行的方法大的输入来解决这个问题的时候 -

  N = 100000; //%输入数据大小VEC =兰迪(100,1,N); //%随机输入
切=兰迪(2,1,N)-1;DISP('--------------------随着CUMSUM + ACCUMARRAY')
抽搐
ID = cumsum(切)+1;
面膜=切== 0;
OUT = accumarray(ID(屏蔽)',VEC(面罩)。[] @(X){X});
TOCDISP('--------------------与find + ARRAYFUN')
抽搐
N = numel(VEC);
IND =找到(切);
ind_before = [IND-1 N]; ind_before(ind_before&所述; 1)= 1;
ind_after = [1的ind + 1]; ind_after(ind_after将N)= N;
出= arrayfun(@(X,Y)VEC(X:Y),ind_after,ind_before,'单向',0);
TOCDISP('--------------------随着CUMSUM + ARRAYFUN')
抽搐
cutsum = cumsum(切);
cutsum(切== 1)= NaN的; %不包括削减指标本身
sumvals =唯一的(cutsum); %查找值索引VEC用于输出
sumvals(isnan(sumvals))= []; %的sumvals删除NaN值
输出= arrayfun(@(VAL)VEC(cutsum == VAL),sumvals,'UniformOutput',0);
TOC

运行时

  --------------------随着CUMSUM + ACCUMARRAY
所用时间是0.068102秒。
--------------------随着FIND + ARRAYFUN
所用时间是0.117953秒。
--------------------随着CUMSUM + ARRAYFUN
所用时间是12.560973秒。


特殊情况:在某些情况下可能有运行的 1 的,你需要修改如下面列出一些东西 -

  //%面膜摆脱切割和VEC对应的人在砍有效值
面膜=切== 0//%的ID设置不同的这个时候。该想法是有连续的ID。
ID = cumsum(切)+1
[〜,〜,ID] =唯一(ID(屏蔽))//%使用屏蔽ID和VEC值终于搞定与accumarray输出
OUT = accumarray(ID(:),VEC(屏蔽)',[],@(X){X})

样运行这样的情况下 -

 >> VEC
VEC =
     1 2 3 4 5 6 7 8 9 10
>>切
切=
     1 0 0 1 1 0 0 0 1 0
>> celldisp(出)
出{1} =
     2
     3
出{2} =
     6
     7
     8
出{3} =
    10

I'm trying to elegantly split a vector. For example,

vec = [1 2 3 4 5 6 7 8 9 10]

According to another vector of 0's and 1's of the same length where the 1's indicate where the vector should be split - or rather cut:

cut = [0 0 0 1 0 0 0 0 1 0]

Giving us a cell output similar to the following:

[1 2 3] [5 6 7 8] [10]

解决方案

Solution code

You can use cumsum & accumarray for an efficient solution -

%// Create ID/labels for use with accumarray later on
id = cumsum(cut)+1   

%// Mask to get valid values from cut and vec corresponding to ones in cut
mask = cut==0        

%// Finally get the output with accumarray using masked IDs and vec values 
out = accumarray(id(mask).',vec(mask).',[],@(x) {x})


Benchmarking

Here are some performance numbers when using a large input on the three most popular approaches listed to solve this problem -

N = 100000;  %// Input Datasize

vec = randi(100,1,N); %// Random inputs
cut = randi(2,1,N)-1;

disp('-------------------- With CUMSUM + ACCUMARRAY')
tic
id = cumsum(cut)+1;
mask = cut==0;
out = accumarray(id(mask).',vec(mask).',[],@(x) {x});
toc

disp('-------------------- With FIND + ARRAYFUN')
tic
N = numel(vec);
ind = find(cut);
ind_before = [ind-1 N]; ind_before(ind_before < 1) = 1;
ind_after = [1 ind+1]; ind_after(ind_after > N) = N;
out = arrayfun(@(x,y) vec(x:y), ind_after, ind_before, 'uni', 0);
toc

disp('-------------------- With CUMSUM + ARRAYFUN')
tic
cutsum = cumsum(cut);
cutsum(cut == 1) = NaN;  %Don't include the cut indices themselves
sumvals = unique(cutsum);      % Find the values to use in indexing vec for the output
sumvals(isnan(sumvals)) = [];  %Remove NaN values from sumvals
output = arrayfun(@(val) vec(cutsum == val), sumvals, 'UniformOutput', 0);
toc

Runtimes

-------------------- With CUMSUM + ACCUMARRAY
Elapsed time is 0.068102 seconds.
-------------------- With FIND + ARRAYFUN
Elapsed time is 0.117953 seconds.
-------------------- With CUMSUM + ARRAYFUN
Elapsed time is 12.560973 seconds.


Special case scenario: In cases where you might have runs of 1's, you need to modify few things as listed next -

%// Mask to get valid values from cut and vec corresponding to ones in cut
mask = cut==0  

%// Setup IDs differently this time. The idea is to have successive IDs.
id = cumsum(cut)+1
[~,~,id] = unique(id(mask))

%// Finally get the output with accumarray using masked IDs and vec values 
out = accumarray(id(:),vec(mask).',[],@(x) {x})

Sample run with such a case -

>> vec
vec =
     1     2     3     4     5     6     7     8     9    10
>> cut
cut =
     1     0     0     1     1     0     0     0     1     0
>> celldisp(out)
out{1} =
     2
     3
out{2} =
     6
     7
     8
out{3} =
    10

这篇关于在MATLAB分裂矢量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆