Increase size of array within cellfun

조회 수: 1 (최근 30일)
Jack
Jack 2023년 9월 19일
편집: Dyuman Joshi 2023년 9월 19일
I have a cell array with each cell containing a 4x4 double array. I want to add an additional value at position (5,5), and thus increase the size of each double array to 5x5. The double arrays will not always be 4x4, but whatever nxm is, I just need to append one additional element in the (n+1)x(m+1) position
I'd rather avoid looping over each cell, can this be done with cellfun? My code below uses '=' within cellfun which is not supported.
n = 4;
m = 4;
A = rand(n,m); B = rand(n,m); C = rand(n,m); D = rand(n,m);
ABCD = {A,B;C,D}; % 2x2 cell array
% ABCD = cellfun(@(x) x(end+1,end+1) = 0, ABCD) % code that doesn't work
Thanks!

채택된 답변

Voss
Voss 2023년 9월 19일
cellfun performs a loop internally, so I think an explicit for loop in this case is fine.
However, if you want to use cellfun, here are a couple of ways:
n = 4;
m = 4;
A = rand(n,m); B = rand(n,m); C = rand(n,m); D = rand(n,m);
ABCD = {A,B;C,D}; % 2x2 cell array
Method 1: Use a helper function (here it's called extend_matrix_by_one and it's defined at the end):
ABCD_new = cellfun(@extend_matrix_by_one, ABCD, 'UniformOutput',false)
ABCD_new = 2×2 cell array
{5×5 double} {5×5 double} {5×5 double} {5×5 double}
ABCD_new{1} % check the first cell
ans = 5×5
0.2104 0.2399 0.3693 0.1618 0 0.0287 0.2169 0.9291 0.0706 0 0.4770 0.9847 0.5352 0.5272 0 0.0211 0.3015 0.8597 0.8126 0 0 0 0 0 0
Method 2: Use subsasgn to do the assignment:
ABCD_new = cellfun(@(x) subsasgn(x,substruct('()',{size(x,1)+1,size(x,2)+1}),0), ABCD, 'UniformOutput',false)
ABCD_new = 2×2 cell array
{5×5 double} {5×5 double} {5×5 double} {5×5 double}
ABCD_new{1} % check the first cell
ans = 5×5
0.2104 0.2399 0.3693 0.1618 0 0.0287 0.2169 0.9291 0.0706 0 0.4770 0.9847 0.5352 0.5272 0 0.0211 0.3015 0.8597 0.8126 0 0 0 0 0 0
% helper function definition
function x = extend_matrix_by_one(x)
x(end+1,end+1) = 0;
end

추가 답변 (1개)

Dyuman Joshi
Dyuman Joshi 2023년 9월 19일
편집: Dyuman Joshi 2023년 9월 19일
"I'd rather avoid looping over each cell, can this be done with cellfun?"
That's the thing - Cellfun is just a loop in disguise.
Looping is the way to go here.
%Bigger Cell array for testing
n = 800;
m = 1000;
A = rand(n,m); B = rand(n,m); C = rand(n,m); D = rand(n,m);
ABCD = {A,B;C,D;A,B;C,D;A,B;C,D;A,B;C,D;A,B;C,D;A,B;C,D;A,B;C,D;A,B;C,D};
%value to append
val = 2;
F1 = @() CELL(ABCD,n,m,val);
F2 = @() LOOP(ABCD,n,m,val);
isequal(F1(),F2())
ans = logical
1
fprintf('Time taken by cellfun = %f seconds', timeit(F1))
Time taken by cellfun = 0.083916 seconds
fprintf('Time taken by loop = %f seconds', timeit(F2))
Time taken by loop = 0.062760 seconds
%% If you want to use cellfun, this is one way to do it
function z = CELL(z,n,m,val)
z = cellfun(@(x) [x zeros(n,1);zeros(1,m) val], z, 'uni', 0);
end
%% Loop method
function z = LOOP(z,n,m,val)
for k=1:numel(z)
z{k}(n+1,m+1) = val;
end
end
  댓글 수: 1
Dyuman Joshi
Dyuman Joshi 2023년 9월 19일
Let's compare the speed of all approaches in this thread -
%Bigger Cell array for testing
n = 800;
m = 1000;
A = rand(n,m); B = rand(n,m); C = rand(n,m); D = rand(n,m);
ABCD = {A,B,C,D;A,B,C,D;A,B,C,D;A,B,C,D;A,B,C,D;A,B,C,D};
%value to append
val = 2;
F1 = @() CELL(ABCD,n,m,val);
F2 = @() LOOP(ABCD,n,m,val);
F3 = @() SUBTITUTE(ABCD,n,m,val);
F4 = @() HELPER(ABCD,val);
%% Check if outputs are equal or not
isequal(F1(),F2(),F3(),F4())
ans = logical
1
fprintf('Time taken by cellfun = %f seconds', timeit(F1))
Time taken by cellfun = 0.074146 seconds
fprintf('Time taken by loop = %f seconds', timeit(F2))
Time taken by loop = 0.060283 seconds
fprintf('Time taken by substitute = %f seconds', timeit(F3))
Time taken by substitute = 0.076276 seconds
fprintf('Time taken by helper = %f seconds', timeit(F4))
Time taken by helper = 0.076179 seconds
function z = CELL(z,n,m,val)
z = cellfun(@(x) [x zeros(n,1);zeros(1,m) val], z, 'uni', 0);
end
function z = LOOP(z,n,m,val)
for k=1:numel(z)
z{k}(n+1,m+1) = val;
end
end
function z = SUBTITUTE(z,n,m,val)
z = cellfun(@(x) subsasgn(x,substruct('()',{n+1,m+1}),val), z, 'UniformOutput',false);
end
function z = HELPER(z,val)
z = cellfun(@(x) extend_matrix_by_one(x,val), z, 'UniformOutput',false);
% helper function definition
function x = extend_matrix_by_one(x,val)
x(end+1,end+1) = val;
end
end

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

제품


릴리스

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by