MATLAB: Transform NaN into number

nanstructstructures

Hi everyone,
I have data that is organized in structures which look like this:
rating.pretest.s1
rating.pretest.s2
...
and in those structures on the last level (s1, s2…) I have numbers or NaN where a participant failed to push a button in time. Since this counts as a wrong answer I would like to assign all the NaNs the number 1. What I tried is
rating(isnan(rating)) = 1
but I got the error message Undefined function "isnan" for input arguments of type "struct". I have read some answers on similar questions but none of them seemed applicable since I'm using a structure (or were too complicated for me to understand since I'm still a beginner). Is there an alternative I could use? Thank you in advance!

Best Answer

For this application, I'd use fillmissing. It will do the same task as filling in locations using logical indexing with the output of isnan, but in the code I find it makes the intent clearer to the reader. In the example below I'm going to assign the output of fillmissing into a different struct array so you can compare the "before and after", but you could assign the output back into the struct you processed if you want. Let's define some sample data:
rating.pretest.s1 = [4;1;NaN;3];
rating.pretest.s2 = [5;2;0;NaN];
Now let's fill in the missing values with the constant 1. I used 'UniformOutput', false to return the output as a struct array with the same fields as the input.
fillingfunction = @(x) fillmissing(x, 'constant', 1);
rating2.pretest = structfun(fillingfunction, rating.pretest, ...
'UniformOutput', false);
Compare the before and after.
rating.pretest.s1
rating2.pretest.s1
rating.pretest.s2
rating2.pretest.s2
FYI you might want to use table arrays to store your data.
pretestScores = table(rating.pretest.s1, rating.pretest.s2, ...
'VariableNames', {'Test1', 'Test2'}, ...
'RowNames', {'Alice', 'Bob', 'Charlie', 'Doug'})
posttestScores = table(rating.pretest.s1+2, rating.pretest.s2+3, ...
'VariableNames', {'Test1', 'Test2'}, ...
'RowNames', {'Alice', 'Bob', 'Charlie', 'Doug'})
You can even store one or more table arrays inside another table!
allScores = table(pretestScores, posttestScores)
allScores.Properties.RowNames = pretestScores.Properties.RowNames
Though if you were to build that allScores table you probably wouldn't want to put the student names as the RowNames of the inner table arrays as well, as that looks kind of funny. You can trim them if you want.
allScores.pretestScores.Properties.RowNames = {}
allScores.posttestScores.Properties.RowNames = {}