How to efficiently access multiple value in a cell [ ACCESS MULTIPLE ROW FOR A SINGLE COLUMN]

Dear Matlab coder, How to access multiple row for a single column in a cell. Currently, I had to use this dumb way to access multiple row for the column 8 as shown below. May I know how to further improve the code? The excel file can be download from DataExcel
function [at] = MeanPVT (at)
for i = 1:length (at.Valindex)
A= (at.Valindex (:,i))';
m1 = (at.raw{A(1),8});
m2 = (at.raw{A(2),8});
m3 = (at.raw{A(3),8});
at.average (i) = (m1+m2+m3)/3;
end
end
On the same note , is it possible to make the code in the function INDEXINGVALUE more compact. Particularly, is there any way I can remove the usage of SWITCH. In the current framework, the state of the CONDITION_3 is depending to the Condition_TTDay. In other word, CONDITION_3 will have 2 or 3 state if the Condition_TTDay is either BL or (SS1 & SS2).
filename = 'DataExcel.xlsx';
[~,~,at.raw] = xlsread(filename,'Sheet1','','basic');
at.Condition_Cond = {'ACond' 'BCond'};
at.Condition_TTDay = {'BL' 'SS1' 'SS2' 'SS3'};
[at] = IndexingValue (at);
[at] = MeanPVT (at);
function [at] = IndexingValue (at)
c= 1;
for i=1:2
for j =1:4
at.condition_1 = at.Condition_Cond {i};
at.condition_2 = at.Condition_TTDay {j};
switch at.condition_2
case 'BL'
for k =1:2
at.condition_3 = k;
at.Valindex (:,c) = calMean (at);
c=c+1;
end
otherwise
for k =1:3
at.condition_3 = k;
at.Valindex (:,c) = calMean (at);
c=c+1;
end
end
end
end
end
function Valindex = calMean (at)
valid = find(cellfun('isclass', at.raw(:,2), 'char') & ...
cellfun('isclass', at.raw(:,3), 'char') & ...
cellfun('isclass', at.raw(:,7),'double'));
Valindex = ...
valid((strcmp(at.raw(valid,2), at.condition_1)) & ...
(strcmp(at.raw(valid,3), at.condition_2)) & ...
([at.raw{valid,7}].' == at.condition_3));
end

3 Comments

Came back to look at your other problem a little more...left with a question:
In calMean the logical array Valindex is going to be for the elements of the raw array as selected by the preceding find operation, NOT for the full raw array. Are you sure this is what you want because you don't decimate raw by the elements not selected to which you then subsequently apply the Valindex vector in MeanPVT.
The procedure's objective in calMean is to find the index location which satisfy both the three precedent condition (i.e., condition_1,2 &3). Thus, if I understand your question correctly, the calMean output is not a logical array but a location (i.e., row number) which satisfy the each of the3 condition. Subsequently, this location will be used in MeanPVT. In MeanPVT, the function will first extract the value at each of the cell depending on row ( store in Valindex) and column (i.e., column eight in this example).
Indeed, the index is ok; while length(valid) is shorter than raw valindex does, indeed, hold the locations relative to the full size so it is correct. I got an extra level of nesting in there while reading code first time and was thinking the shortening would've happened before the find operation but as written it doesn't...is ok, yes. Sorry for the sidetrack.

Sign in to comment.

 Accepted Answer

A first step simplification eliminates superfluous parens and (to my eye, anyway) spaces that make harder to read than without--
for i=1:length(at.Valindex)
A =at.Valindex(:,i).';
m(1)=at.raw{A(1),8};
m(2)=at.raw{A(2),8};
m(3)=at.raw{A(3),8};
at.average(i)=mean(m);
end
which then is seen to be
for i=1:length(at.Valindex)
A =at.Valindex(:,i).';
for j=1:3, m(j)=at.raw{A(j),8}; end
at.average(i)=mean(m);
end
But, addressing by vector for rows for a fixed column is the same result in Matlab--
for i=1:length(at.Valindex)
A =at.Valindex(:,i).';
at.average(i)=mean(at.raw{A(1:3),8});
end
Will be a little more efficient if preallocate at.average to size loop upper limit.
What is at.Valindex, specfically? It may be doable to use arrayfun() or other vector operations and eliminate the loop entirely.
On the other question, I'd venture the answer is probably 'yes' but I'm out of time at the moment; maybe somebody else will take a look there...

5 Comments

Hi DBP, Thanks for the suggested code. The following code work perfectly
for j=1:3, m(j)=at.raw{A(j),8}; end
at.average(i)=mean(m);
However, the technique which address by vector for rows for a fixed column produce an error. Expand the code further, such as
aa =at.raw{A(1:3),8}
at.average(i)=mean(aa);
aa only have ONE value instead of the expected THREE values.
Regarding your question, I have answer it in below the original posting to maintain readability.
Thank you
Well, what are A and raw? Wasn't sure; made some assumptions that may not have been true.
Hi dpb, I am sorry, I forget to attached the excel file together with the question. The excel file can be downloaded from this link DataExcel. .
Under the raw there are several columns. The column 2, 3, and 7 represent the condition_1, condition_2, condition_3, respectively. The variable A represent the index location at Column 8 of the raw for each case that satisfy the three condition.
I hope this make more sense.
Well, that's what I presumed -- without seeing the details of what you did why the vector access wouldn't be precisely the same as the loop -- small demo:
>> raw=randn(10,8); % source array w/ 8 columns
>> A=randi(10,1,3); % pick 3 random indices inside
>> A(1:3) % which three for curiosity
ans =
6 8 10
>> raw(A(1:3),8).' % what do we get?
ans =
-0.1713 1.8702 -0.8394
>> for i=1:3,disp(raw(A(i),8)),end % compare to loop
-0.1713
1.8702
-0.8394
>>
Identically the same three elements were returned...hence
>> mean(raw(A(1:3),8))
ans =
0.2865
>> s=0;for i=1:3,s=s+(raw(A(i),8));end,s/3
ans =
0.2865
>>
are also the same...
There's an implementation error or that's not the actual data arrangement you've got, one...
Hi DBP,
Thanks for the clarification. There are slight implementation error on my side. Thanks for your response

Sign in to comment.

More Answers (0)

Categories

Asked:

on 9 Jul 2017

Edited:

dpb
on 10 Jul 2017

Community Treasure Hunt

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

Start Hunting!