How to replace values in a cell array based on a condition?

I have a cell array 'C' that is 1x525, with each cell holding a matrix with 18 columns and varying rows. I also have cell arrays 'F' and 'G', which are also 1x525, and contain matrices of size 1x18. What I want is: if element C{1,1}(10,14) is greater than F{1,1}(1,14), the element in C should be replaced with said value in F. If C{1,1}(10,14) is less than G{1,1}(1,14), it should be replaced with said value in G. I want to do this for every cell in C with its corresponding cell in F and G, with respect to only columns 8:18. Any ideas are welcome. Here is my code so far as to how I arrived at C, F, and G:
load weekdata.mat
N = size(weekdata,3);
C = cell(1,N); % weekly data
D = cell(1,N); % means
E = cell(1,N); % standard deviations
F = cell(1,N); % 3 z-scores above
G = cell(1,N); % 3 z-scores below
for k = 1:N
idx = weekdata(:,3,k)==0 & weekdata(:,4,k)==0 & weekdata(:,5,k)==1 & weekdata(:,6,k)==0;
tmp = weekdata(idx,:,k);
C{k} = tmp;
if size(C{1,k},1) > 1
D{1,k} = mean(C{1,k});
E{1,k} = std(C{1,k});
else
D{1,k} = C{1,k};
E{1,k} = zeros(1,18);
end
F{k} = D{k}+3*E{k};
G{k} = D{k}-3*E{k};
end

 Accepted Answer

for k = 1:numel(C)
C{k}(:,8:18) = min(F{k}(:,8:18),max(G{k}(:,8:18),C{k}(:,8:18)));
end

5 Comments

Have tried plugging this in, as follows:
N = size(weekdata,3);
C = cell(1,N); % weekly data
D = cell(1,N); % means
E = cell(1,N); % standard deviations
F = cell(1,N); % 3 z-scores above
G = cell(1,N); % 3 z-scores below
A = cell(1,N);
for k = 1:N
idx = weekdata(:,3,k)==0 & weekdata(:,4,k)==0 & weekdata(:,5,k)==1 & weekdata(:,6,k)==0;
tmp = weekdata(idx,:,k);
C{k} = tmp;
if size(C{1,k},1) > 1
D{1,k} = mean(C{1,k});
E{1,k} = std(C{1,k});
else
D{1,k} = C{1,k};
E{1,k} = zeros(1,18);
end
F{k} = D{k}+3*E{k};
G{k} = D{k}-3*E{k};
end
for k = 1:numel(C)
C{k}(:,8:18) = min(F{k}(:,8:18),max(G{k}(:,8:18),C{k}(:,8:18)));
end
But I get the following error:
Error using max
Matrix dimensions must agree.
Error in multi_factor_analysis (line 25)
C{k}(:,8:18) = min(F{k}(:,8:18),max(G{k}(:,8:18),C{k}(:,8:18)));
Any ideas?
@Neal Mannan Hasan: what MATLAB version are you using? For versions pre R2016b you might need to use bsxfun for each of min and max, e.g.:
for k = 1:numel(C)
tmp = C{k}(:,8:18);
tmp = bsxfun(@max,tmp,G{k}(:,8:18));
tmp = bsxfun(@min,tmp,F{k}(:,8:18));
C{k}(:,8:18) = tmp;
end
Ah that fixed it, I'm on R2014a, this company runs a pretty old version :) However, I want to replace values greater than F and less than G; does this do that or the opposite? I only ask as the @max is with G{k} and @min with F{k}, but perhaps I misunderstand the functionality?
"I only ask as the @max is with G{k} and @min with F{k}, but perhaps I misunderstand the functionality?"
Your question states "If C{1,1}(10,14) is less than G{1,1}(1,14), it should be replaced with said value in G".
This means that you want the output to have the maximum of the values in C and G: if C is less than G and you replace C with G then this is the maximum of C and G. You can easily check this yourself, and decide if it is doing what you want it to do:
>> C = [2,4,8;1,2,3]
C =
2 4 8
1 2 3
>> G = [0,3,9];
>> bsxfun(@max,C,G)
ans =
2 4 9
1 3 9

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!