快速方法将不同长度的Matrix行存储到Cell中

时间:2016-12-12 08:56:12

标签: arrays matlab loops vectorization cell-array

我有三个矩阵:

Values = [200x7] doubles
numOfStrings = [82    78    75    73    72    71    70] %(for example)
numOfColumns = [1 4] 

numOfColumns可以包含1到7之间的任何一组不同值。例如[1 2 3][4 7][1 5 6 7]。显然,最大的numOfColumns可能是[1 2 3 4 5 6 7]

numOfColumns显示我想要的列。 numOfStrings显示了我需要的列的行。即在我的示例中,我希望获得列14。因此,在1列中,我希望获得82第一行,并从4th获取73第一行。

即。如果numOfColumns = [1 4]那么

myCell{1} = Values( 1:82,1); % Values(numOfStrings(numOfColumn(1)), numOfColumn(1))
myCell{2} = Values( 1:73,4); % Values(numOfStrings(numOfColumn(2)), numOfColumn(2))

P.S。没有必要将它保存到单元阵列中。如果您能提供任何其他解决方案我将不胜感激。

我正在寻找最快的方法,这可能是通过避免for循环和使用矢量化来实现的。

我对sub2ind功能有很多了解。但我无法弄清楚如何返回不同大小的数组!因为myCell{1} - [82x1]myCell{2} - [73x1]。我想我不能使用bsxfunarrayfun

结果:

  1. 使用for循环@Will 's answer

    for jj = 1:numel(numOfColumns)
        myCell{rowNumber(numOfColumns(jj)),numOfColumns(jj)} = Values( 1:numOfStrings(numOfColumns(jj)),numOfColumns(jj));
    end
    

    经过的时间是157秒

  2. 使用arrayfun类似@Yishai E 's answer

    myCell(sub2ind(size(myCell),rowNumber(numOfColumns),numOfColumns)) = arrayfun( @(nOC) Values( 1:numOfStrings(nOC),nOC), numOfColumns, 'UniformOutput', false);
    

    经过的时间是179秒

  3. 使用bsxfun类似@rahnema1 's answer

    idx = bsxfun(@ge,numOfStrings , (1:200).');
    extracted_values = Values (idx);
    tempCell = mat2cell(extracted_values,numOfStrings);
    myCell(sub2ind(size(myCell),rowNumber(numOfColumns),numOfColumns)) = myCell(numOfColumns)';
    

    经过的时间是204秒

  4. 所以,我得到了很多工作答案,其中一些是我提出的矢量化,但for循环仍然最快!

3 个答案:

答案 0 :(得分:2)

这可以解决您的问题,使用arrayfun,它“索引”索引函数的应用程序。不是真的,但它没有为numOfColumns中的每个条目调用解释器。有趣的是,这比其他答案中的非矢量化代码要慢! (对于1e5条目,0.95秒对0.23秒......)

arrayfun(@(nOC)Values(1:numOfStrings(nOC), nOC), numOfColumns, 'UniformOutput', false)

答案 1 :(得分:1)

% Get number of elements in NUMOFCOLUMNS
n = numel(numOfColumns);

% Set up output
myCell = cell(1,n);    

% Loop through all NUMOFCOLUMNS values, storing to cell
for i = 1:n

    myCell{i} = Values(1:numOfStrings(numOfColumns(i)), numOfColumns(i));

end 

为您的示例提供输出

myCell = 

[82x1 double]    [73x1 double]

答案 2 :(得分:1)

您可以创建用于提取所需元素的逻辑索引:

idx = bsxfun(@ge,numOfStrings , (1:200).');

在MATLAB R2016b或Octave中(由于广播/扩展)可以写成:

idx = numOfStrings >= (1:200).';

提取值:

extracted_values = Values (idx);

然后使用mat2cell将数据转换为单元格:

myCell = mat2cell(extracted_values,numOfStrings);

全部在一行:

myCell = mat2cell(Values (numOfStrings >= (1:200).'), numOfStrings);

如果您想使用不同大小的不同numOfColumns来提取单元格的元素,您每次都可以这样做:

result = myCell(numOfColumns);

如果numOfStringsnumOfColumns都发生了变化,您需要在执行此操作后计算结果:

%convert numOfColumns to logical index:
numcols_logical = false(1,7);
numcols_logical(numOfColumns) = true;
extracted_values = Values ((numOfStrings .* numcols_logical) >= (1:200).');

如果你需要单元格数组

result= mat2cell(extracted_values,numOfStrings(numcols_logical));