How to extract valid and invalid values from 1 array into 2 new arrays?

4 vues (au cours des 30 derniers jours)
Halima Rafi
Halima Rafi le 16 Déc 2020
Modifié(e) : Stephen23 le 30 Déc 2020
Dear Experts,
I have a cell matrix called CombinedData (attached) with 3 colulmns. The first column, CondFinal, specifies 8 conditions, the second column specifies onsets and the third column specifies validity (which only matters for half of the conditions, 1 = invalid trial, 2 = valid trial).
I need to do identify invalid trials and then do 2 things: 1) remove them from CombinedData1 and 2) create a new matrix with (which I've called invalidtrials) to store the invalid trial conditions and onsets in. My code isn't efficient but it's working for part one but I can't seem to extract the invalid trials and put them in a new matrix.
CombinedData = [CondFinal allonsets valid_cell]; % all valid and invalid trials together
Condfinal1 = cellstr(CondFinal); %convert to str for easier handling
CombinedData1 = [Condfinal1 allonsets valid_cell]; % matrix to be modified into only valid trials
%Apos, Aneg, Bpos and Bneg are the conditions with invalid trials (specified in column 1)
% column 3 speificies invalid trials as 1 and valid trials as 0
for p = 1:length(CombinedData1)
invalid1 = double(strcmp(CombinedData1(:,1), "Apos")+1); %value will become 2
invalid2 = double(strcmp(CombinedData1(:,1), "Aneg")+1); %value will become 2
invalid3 = double(strcmp(CombinedData1(:,1), "Bpos")+1); %value will become 2
invalid4 = double(strcmp(CombinedData1(:,1), "Bneg")+1); %value will become 2
invalid5 = double(strcmp(CombinedData1(:,3),'1')+1); % column 3 specifies invalid trials=1, valid trials=0
% if there is an invalid trial for conditions Apos, Aneg, Bpos, Bneg, the sum will equal 4
type1 = invalid1+invalid5;
type2 = invalid2+invalid5;
type3 = invalid3+invalid5;
type4 = invalid4+invalid5;
%create new matrix for invalid trials to be moved to
invalidtrials = CombinedData1;
mask = type1 > 3 | type2 > 3 | type3 > 3 | type4 > 3; %mask finds invalid trials (value of 4)
mask2 = type1 < 4 | type2 < 4 | type3 < 4| type4 < 4; %mask2 finds all valid trials (value less than 4)
%remove invalid trials from CombinedData1
CombinedData1(mask,:) = [];
%remove valid trials from invalidtrials
invalidtrials(mask2,:) = [];
end

Réponses (2)

Anshika Chaurasia
Anshika Chaurasia le 30 Déc 2020
Hi Halima,
It is my understanding that mask and mask2 are logical arrays for invalid and valid trials respectively.
So, you should use find function to get index at which logic is 1(or 0) and then remove invalid and valid trials as per your requirement.
You can use the following snippet:
%remove invalid trials from CombinedData1
CombinedData1(find(~mask),:) = [];
%remove valid trials from invalidtrials
invalidtrials(find(~mask2),:) = [];
Refer to the example for more information on finding indices.
  1 commentaire
Stephen23
Stephen23 le 30 Déc 2020
find is not required, logical indexing is simpler and more efficient.

Connectez-vous pour commenter.


Stephen23
Stephen23 le 30 Déc 2020
Modifié(e) : Stephen23 le 30 Déc 2020
The loop does nothing, get rid of it. Using find will not solve your problem.
The actual problem is that your logic for either mask or mask2 is flawed. Most likely you wrote thinking that mask and mask2 are negations of each other, but (~A|~B) is NOT the negation of (A|B). In fact the negation of (A|B) is (~A&~B). So you used the wrong operator. But in any case, it is very bad code style to define the logic twice like that (because it increases the risk of bugs and inconsistencies, as you have found out). The much better approach is to simply create one mask and then negate it when you use it:
% simpler:
invalid1 = 1+strcmp(CombinedData1(:,1),'Apos');
invalid2 = 1+strcmp(CombinedData1(:,1),'Aneg');
invalid3 = 1+strcmp(CombinedData1(:,1),'Bpos');
invalid4 = 1+strcmp(CombinedData1(:,1),'Bneg');
invalid5 = 1+strcmp(CombinedData1(:,3),'1'); % in/valid==1/0
% if there is an invalid trial for conditions Apos, Aneg, Bpos, Bneg, the sum will equal 4
type1 = invalid1+invalid5;
type2 = invalid2+invalid5;
type3 = invalid3+invalid5;
type4 = invalid4+invalid5;
%create new matrix for invalid trials to be moved to
invalidtrials = CombinedData1;
mask = type1 > 3 | type2 > 3 | type3 > 3 | type4 > 3; % check this!
%remove invalid trials from CombinedData1
CombinedData1(mask,:) = [];
%remove valid trials from invalidtrials
invalidtrials(~mask,:) = [];
% ^ one negation
Most likely your code would be more robust if you actually used logical operators instead of the indirect method of converting to numeric and adding them, e.g.:
Apo = strcmp(CombinedData1(:,1),'Apos');
Ane = strcmp(CombinedData1(:,1),'Aneg');
Bpo = strcmp(CombinedData1(:,1),'Bpos');
Bne = strcmp(CombinedData1(:,1),'Bneg');
ivd = strcmp(CombinedData1(:,3),'1'); % in/valid==1/0
idx = Apo|Ane|Bpo|Bne;
idi = idx & ivd; % invalid mask
idv = idx & ~ivd; % valid mask
Ari = CombinedData1(idi,:);
Arv = CombinedData1(idv,:);
Note that the logic implemented here is slightly different: both output arrays only include when the first coumn has values Apos,Aneg,Bpos,Bneg, any other values are not returned. If there are no other values in the first column then the difference is moot. Of course you should check and change the logic to suit your data and requirements!

Catégories

En savoir plus sur Line Plots dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by