How to make matrix dimensions the same size?
    6 views (last 30 days)
  
       Show older comments
    
    Jessica Dawson
 on 23 Jul 2020
  
    
    
    
    
    Commented: Jessica Dawson
 on 26 Jul 2020
            I have data which currently is a fixation report. This means it has starting fixations (SF) and end fixations (EF). For example, in one row the fixation has an SF of 7 and an EF of 50. So one row is 1 fixation with the start and end time.
I want to turn this data into one row per milisecond (in my case there is 39500msec so 39500 rows). With a 1 if there is currently a fixation and 0 if there isnt. With this per participant (PPT).
I have tried to following but get the error message that 'Matrix dimensions must agree'. 
I am new to Matlab!
data = readtable('data.txt','HeaderLines',1,'Delimiter','\t');
    PPT=data.Var1;
    clip=data.Var2;
    condition=data.Var3;
    SF=data.Var4;
    EF=data.Var4;
    OnSpeaker=data.Var6;
UP = unique(PPT);
jj=1:39500;
timeMsec=transpose(jj);
for x=1:length(UP) %loop through all the unique participants
for z=1:length(OnSpeaker) %loop through the length of the data
timeseries=zeros(39500,1);
end   
for f = 1:length(SF); 
if SF>= timeMsec & EF<=timeMsec    % This is definitely the bit thats wrong!!
timeseries=1;
else timeseries=0,
end
end
3 Comments
Accepted Answer
  neil jerome
      
 on 23 Jul 2020
        
      Edited: neil jerome
      
 on 23 Jul 2020
  
      % fixation time script
% read data
data = readtable('data.txt','HeaderLines',1,'Delimiter','\t'); % see my 'data.txt' below
PPT = data.Var1;
clip = data.Var2;
condition = data.Var3;
SF = data.Var4;
EF = data.Var5;
OnSpeaker = data.Var6;
UP = unique(PPT); nUP = length(UP);
maxTime = 20; % end recording time in ms
% assign matrix: rows are time, cols are UP
dataMat = zeros(maxTime, nUP);
%%
for aa = 1:nUP % loop for unique participants
    thisUP = UP{aa};
    thisUPdata = strcmp(thisUP, PPT); % find which rows for this UP
    for bb = 1:length(PPT) % work through line by line
        if thisUPdata(bb) % if this line if for the current UP
            dataMat(SF(bb):EF(bb)-1, aa) = 1; % assign ones for fixation
        end
    end
end
%% add time column if you want to
fullTable = horzcat((1:maxTime)',dataMat);
%% here is the data.txt, modified to show multiple UP, and much shorter :)
% PPT	Clip	Cond	SF	EF	OnSpeaker?
% ppt15a	Group1_Clip1_NaturalX.xvd	Natural	2	5	0
% ppt15a	Group1_Clip1_NaturalX.xvd	Natural	7	9	0
% ppt15a	Group1_Clip1_NaturalX.xvd	Natural	12	14	0
% ppt18a	Group1_Clip1_NaturalX.xvd	Natural	3	9	1
% ppt18a	Group1_Clip1_NaturalX.xvd	Natural	10	12	1
% ppt18a	Group1_Clip1_NaturalX.xvd	Natural	15	16	1
% ppt20a	Group1_Clip1_NaturalX.xvd	Natural	4	19	1
5 Comments
  neil jerome
      
 on 24 Jul 2020
				different ways to do this, so what is 'best is very subjective/dependent on what you're doing next. and that's assuming i understand what you mean :) 
what you have here looks ok to start, but: 
you only have a one-dimensional dataSpeak, which either implies that the speakerOn condition is the same regardless of participant (ie all participants get the same timings), or you're overwriting this every time you loop to the next UP. so if this would be bad, you need to make it a matrix with size that matches dataMat where you can assign a separate dataSpeak column for each UP. so you have corresponding entries in dataMat and dataSpeak (or you could combine these into a single 3D matrix, with the first layer fixation and the second layer speakerOn; this is more compact, but less 'readable'):
for bb = 1:length(PPT) % work through line by line
        if thisUPdata(bb) % if this line is for the current UP
            dataMat(SF(bb):EF(bb)-1, aa) = 1; % assign ones for fixation
            % extra line that assigns speakerOn in the same indices as you have the fixation
            dataSpeak(SF(bb):EF(bb)-1, aa) = OnSpeaker(bb); % assign [-1,0,1] for speaker
        end
end
although this would give you 'valid' dataSpeak values only where there were fixations, and so you could initialise the array as NaNs, not zeros, so you don't get any 'default zeros' that weren't explicitly put there by reading the data file. (though beware using NaNs in tables when you do any other maths on the table, you need to use nansum() instead of sum(), etc)
hope that makes sense; if i've misunderstood, sorry. but i have assumed that you only really care about the speaker when you record a fixation, otherwise you would have some separate listing of speakerOn that wasn't linked to fixation events?
couple of notes on what you wrote: since OnSpeaker has the value you will write to your data matrix, you don't need to go through testing for each value and then explicitly assign those same values! so you can save space/time:
            if OnSpeaker(bb)==1 & dataMat(bb)==1 % use double: && as the boolean 'and' operator
            dataSpeak(bb)=1;
            end
            if OnSpeaker(bb)==0 & dataMat(bb)==1
                dataSpeak(bb)=0;
            end
            if OnSpeaker(bb)==-1 & dataMat(bb)==1
                dataSpeak(bb)=-1;
            end
            % all this becomes
            if dataMat(bb) % no need to write '==1' the 'if' will return true for value of 1
                dataSpeak(bb) = OnSpeaker(bb);
            end
ok, back to work.
More Answers (0)
See Also
Categories
				Find more on Loops and Conditional Statements in Help Center and File Exchange
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!

