关于变量分配:在Matlab中设置单元格数组中每个矩阵的最后一个值

Setting the last value of each matrix in a cell array in Matlab

我有一个单元格数组,其中每个单元格都包含一个大小相同的矩阵。如何有效设置数组中每个矩阵的最后一个条目?我试图使用cellfun,但看起来不可能赋值。

最小的工作示例(我能想到的最有效的实现):

1
2
3
4
5
6
7
8
9
C = cell(5, 6, 7);
[C{:}] = deal(ones(10, 1));
for i = 1:5
    for j = 1:6
        for k = 1:7
            C{i,j,k}(end) = 0;
        end
    end
end


我认为最好的方法是更改??您的原始输入。你能没有牢房生活吗?这些通常仅在您具有异构数据时使用。

尝试将每个单元格设置为数组的页面(其中页面是三维尺寸)(因此现在它只是一个普通的3D数组)。

然后,您应该能够直接索引到每个页面的最后一个条目。


这是一种无需循环的方法。这允许

  • 包含矩阵的单元格(不一定如您的示例中的矢量);和
  • 每个单元格的期望值都不同(不一定与您的示例相同)。

代码:

1
2
3
4
5
C = repmat({zeros(2,3)}, 4, 5, 6); % example cell array with matrices
values = 1:numel(C); % example vector with numel(C) values. Or it can be a scalar
t = cat(3, C{:}); % temporarily concatenate all matrices into 3D array
t(end,end,:) = values; % set last value of each matrix
C = reshape(num2cell(t, [1 2]), size(C)); % convert back

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>> whos C
  Name      Size             Bytes  Class    Attributes

  C         4x5x6            19200  cell              

>> C{1,1,1}
ans =
     0     0     0
     0     0     1
>> C{2,1,1}
ans =
     0     0     0
     0     0     2
>> C{4,5,6}
ans =
     0     0     0
     0     0   120

选项1

创建函数(例如在单独的文件中)

1
2
3
function x = assignAtEnd(x, v)
  x(end) = v;
end

并按如下所示执行cellfun

1
B = cellfun(@(x) assignAtEnd(x, 0), C, 'UniformOutput', false);

这将为您提供一个B单元格数组,其末尾的所有值均更改为0。

但是,我认为这并不比for循环快很多。实际上,它可能会更慢。我用1.000.000个单元格元素(100、100、100)进行了测试,我的计算机上的结果如下:

1
2
3
for-loop (3D): 3.48 sec
for-loop (1D as per @mikkola): 2.67 sec
cellfun: 3.06 sec

选项2

如果每个单元格包含大小相同的矩阵,并且您的应用程序对时间要求严格,那么事实证明,将单元格数组转换为数字数组,执行操作并将其转换回单元格数组的速度更快。 >

1
2
3
4
5
6
7
8
9
10
11
12
% creating the cell
cellDim = 100;
matrixDim = 10;
C = cell(cellDim, cellDim, cellDim);
[C{:}] = deal(1:matrixDim);

% converting to a 4D numeric matrix
A = reshape(cell2mat(C), cellDim, matrixDim, cellDim, cellDim);
% assigning the 0s
A(:,end,:,:) = 0;
% converting back to a cell
B = squeeze(num2cell(A, 2));

实际上,转换回单元格的最后一行花费了大部分时间。该操作总共需要

1
with numeric conversion: 1.93 sec

但是,其中的1.40 sec用于转换回单元阵列,因此您的操作仅需0.5 sec,速度提高了5倍!

出于完整性考虑,我还对@LuisMendo的出色答案进行了时间测试,结果为

1
with numeric conversion (@LuisMendo): 1.66 sec

外卖留言

如果具有相同尺寸的数据,请避免使用单元格数组!使用更高维的数字数组。