How to replace all Inf values in a cell array with NaN?

2k Views Asked by At

I have a 2-by-54 cell array in Matlab. Occasionally, the second row contains some Inf values. I'd like to convert all Inf values to NaN values and tried using this code:

dataC(cellfun(@isinf, dataC, 'UniformOutput', false)) = {NaN};

where dataC is my cell array.

However, when doing that I get the following error:

Error using subsindex

Function 'subsindex' is not defined for values of class 'cell'.

How can I solve this problem?

2

There are 2 best solutions below

5
On

To use the approach you proposed in the question, remove the UniformOutput-property, this way a logical index is returned and the elements can be addressed directly. This works only when the cell content is scalar!

dataC(cellfun(@isinf, dataC)) = {NaN};

Edit: Thanks @Luis Mendo for mentioning, that the use of find is not needed here. My original solution has been dataC(find(cellfun(@isinf,dataC))) = {NaN} and used the unnecessary find in the addressing of dataC.

In case you have arrays in the cells, use the following approach: Write your own function and provide it as a function handle. In the following code I implemented the function replaceInf to do the replacement.

function demo
    dataC = ones(2,4);         % generate example data
    dataC = num2cell(dataC);   % convert data to cell array
    dataC{2,3} = Inf;          % assign an Inf value
    dataC{1,2} = [1 2 Inf 3]   % add an array to cell
    dataC{1,2}                 % show the cell

    dataC = cellfun(@replaceInf, dataC, 'UniformOutput', false)
    dataC{1,2}                 % show the array in the cell

end

function out = replaceInf(in)
    in(isinf(in)) = NaN;
    out = in;
end

This gives the following output:

dataC = 
    [1]    [1x4 double]    [  1]    [1]
    [1]    [         1]    [Inf]    [1]
ans =
     1     2   Inf     3
dataC = 
    [1]    [1x4 double]    [  1]    [1]
    [1]    [         1]    [NaN]    [1]
ans =
     1     2   NaN     3
0
On

I'm assuming that you don't just have scalars in each cell? Otherwise why are you using a cell array at all?

In order to use cellfun you need to convert Inf to NaN but do so without using the assignment operator (i.e. =).

If you add NaN to Inf it returns NaN so my strategy is to create a matrix with NaN where you have Inf and 0 otherwise. isinf finds the Inf elements but unfortunately 0*NaN is NaN so you can't just add isnan(...).*NaN. However, 0/0 is indeterminate which Matlab returns NaN for and 0/1 is zero hence 0./~isnan(...) returns what we need. Putting it all together:

cellfun(@(x)(x + 0./~isinf(x)), dataC, 'UniformOutput', false)

I think this will break if you have cells within cells though...