串联通过一个单元阵列的一维子电池,而不在MATLAB使用循环 [英] Concatenate subcells through one dimension of a cell array without using loops in MATLAB

查看:440
本文介绍了串联通过一个单元阵列的一维子电池,而不在MATLAB使用循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个单元阵列。每个单元包含可变长度的向量。例如:

I have a cell array. Each cell contains a vector of variable length. For example:

example_cell_array=cellfun(@(x)x.*rand([length(x),1]),cellfun(@(x)ones(x,1), num2cell(ceil(10.*rand([7,4]))), 'UniformOutput', false), 'UniformOutput', false)

我需要向下通过一个尺寸来连接的单元的内容,然后在每个级联矢量生成标量执行操作用于我的单元阵列的每一列(例如总和()例如 - 实际操作复杂,费时,和不自然vectorisable - 尤其是对diffent长度vecotrs)

I need to concatenate the contents of the cells down through one dimension then perform an operation on each concatenated vector generating scalar for each column in my cell array (like sum() for example - the actual operation is complex, time consuming, and not naturally vectorisable - especially for diffent length vecotrs).

我可以按如下方式使用易循环(我的级联向量和示例)做到这一点:

I can do this with loops easily (for my concatenated vector sum example) as follows:

[M N]=size(example_cell_array);
result=zeros(1,N);
cat_cell_array=cell(1,N);
for n=1:N
    cat_cell_array{n}=[];
    for m=1:M
        cat_cell_array{n}=[cat_cell_array{n};example_cell_array{m,n}];
    end
end
result=cell2mat(cellfun(@(x)sum(x), cat_cell_array, 'UniformOutput', false))

不幸的是,这是太慢。 (我的单元阵列是1Mx5与每个细胞100-200长度范围载体)

Unfortunately this is WAY too slow. (My cell array is 1Mx5 with vectors in each cell ranging in length from 100-200)

是否有产生,其中包含在细胞中的载体已被级联向下级联单元阵列的简单方法一维

Is there a simple way to produce the concatenated cell array where the vectors contained in the cells have been concatenated down one dimension?

是这样的:

dim=1;
cat_cell_array=(?concatcells?(dim,example_cell_array);

编辑:
既然有这么多的人一直在测试的解决方案:仅供参考,我申请到每个级联的载体功能是circ_kappa(X),可从<一个href=\"http://www.mathworks.com/matlabcentral/fileexchange/10676-circular-statistics-toolbox--directional-statistics-/content/circ_kappa.m\"相对=nofollow>圆形统计工具箱

推荐答案

一些方法可能会建议您从 example_cell_array 使用解压缩的数字数据 { ..} ,然后置后收拾它放回大尺寸的细胞形成的 cat_cell_array 。然后,你又需要从串联单元阵列解压数值数据在每个单元上执行您的操作的。

Some approaches might suggest you to unpack the numeric data from example_cell_array using {..} and then after concatenation pack it back into bigger sized cells to form your cat_cell_array. Then, again you need to unpack numeric data from that concatenated cell array to perform your operation on each cell.

现在,在我看来,这种多压缩和解压缩的方法会不会有效的,如果 example_cell_array 不是你预期的成果之一。因此,考虑到所有这些,让我在这里建议两种方法。

Now, in my view, this multiple unpacking and packing approaches won't be efficient ones if example_cell_array isn't one of your intended outputs. So, considering all these, let me suggest two approaches here.

第一个是一个for循环code -

The first one is a for-loop code -

data1 =  vertcat(example_cell_array{:}); %// extract all numeric data for once
starts = [1 sum(cellfun('length',example_cell_array),1)]; %// intervals lengths
idx = cumsum(starts); %// get indices to work on intervals basis
result  = zeros(1,size(example_cell_array,2)); 
%// replace this with "result(size(example_cell_array,2))=0;" for performance
for k1 = 1:numel(idx)-1
    result(k1) = sum(data1(idx(k1):idx(k1+1)-1));
end

所以,你需要编辑与实际的操作

如果 example_cell_array 有很多栏目,我的第二个建议是一个的几乎的量化方法,但是它不严重或者与执行一个小数量的列。现在这个code使用 cellfun 在第一行以获取在串联版本每个单元的长度。 cellfun 基本上是一个包装循环code,但是这是不是很昂贵的运行而言,这就是为什么我归类这种方法作为的几乎的量化之一。

If example_cell_array has a lot of columns, my second suggestion would be an almost vectorized approach, though it doesn't perform badly either with a small number of columns. Now this code uses cellfun at the first line to get the lengths for each cell in concatenated version. cellfun is basically a wrapper to a loop code, but this is not very expensive in terms of runtime and that's why I categorized this approach as an almost vectorized one.

在code会 -

lens = sum(cellfun('length',example_cell_array),1); %// intervals lengths
maxlens = max(lens);
numlens = numel(lens);
array1(maxlens,numlens)=0;
array1(bsxfun(@ge,lens,[1:maxlens]')) = vertcat(example_cell_array{:}); %//'
result = sum(array1,1);

您现在需要做的事情,就是让你的操作的使用由<$创建的面具与数组1 列的基础上运行C $ C> bsxfun 的实施。因此,如果数组1 的M×5 大小的数组,你需要从每一列使用的有效元素面膜,然后做这些元素的操作的。让我知道如果你需要在屏蔽问题的详细信息。

The thing you need to do now, is to make your operation run on column basis with array1 using the mask created by the bsxfun implementation. Thus, if array1 is a M x 5 sized array, you need to select the valid elements from each column using the mask and then do the operation on those elements. Let me know if you need more info on the masking issue.

希望这些方法之一将努力为您服务!

Hope one of these approaches would work for you!

快速测试:使用 250000x5 尺寸 example_cell_array ,快速测试表明,无论是这些方法对运行表现非常好,并提供有关 400X 加速了在问题的code我的结束。

Quick Tests: Using a 250000x5 sized example_cell_array, quick tests show that both these approaches for the sum operation perform very well and give about 400x speedup over the code in the question at my end.

这篇关于串联通过一个单元阵列的一维子电池,而不在MATLAB使用循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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