1

I have a 4x1 cell array containing string identifiers, and a 4x5 cell array containing 5 data points for each of these entities over time...

>> ids = { '1'; '2'; 'A'; '4' }

ids = 

 '1'
 '2'
 'A'
 '4'

>> vals = { 11, 12, 13, 14, 15; 21, 22, 23, 24, 25; 31, 32, 33, 34, 35;, 41, 42, 43, 44, 45}

vals = 

 [11]    [12]    [13]    [14]    [15]
 [21]    [22]    [23]    [24]    [25]
 [31]    [32]    [33]    [34]    [35]
 [41]    [42]    [43]    [44]    [45]

I want to convert IDs to numbers and strip out data in both cell arrays for non-numeric IDs, leaving:

ids = 

 [1]
 [2]
 [4]

vals = 

 [11]    [12]    [13]    [14]    [15]
 [21]    [22]    [23]    [24]    [25]
 [41]    [42]    [43]    [44]    [45]

I am wondering if the key to this is working out which indexes are empty and then addressing both cell arrays with these indexes, but I'm not sure where to go after this...

>> numericIds = cellfun(@str2num, ids, 'un', 0)

numericIds = 

 [1]
 [2]
 []
 [4]

>> emptyIdx = cellfun(@isempty, numericIds, 'un', 0)

emptyIdx = 

 [0]
 [0]
 [1]
 [0]

>> ids(emptyIdx) = []
Error using subsindex
Function 'subsindex' is not defined for values of class 'cell'.
1
  • 1
    Do not use the 'uni' 0 flag while getting emptyIdx. I think your problem is that emptyIdx is a cell array which is not going well with indexing. Commented Mar 11, 2016 at 17:00

2 Answers 2

2

As others have said, the root of your problem is that you're trying to use a cell array as an index. This is because the uniform input to cellfun determines whether to return a numeric array (true) of cell array (false).

That being said, I would probably not use cellfun and would probably just use str2double directly on the cell array to figure out which ones are valid numbers (it returns a NaN for non-numbers).

ids = str2double(ids);
tokeep = ~isnan(ids);
ids = ids(tokeep);
vals = vals(tokeep, :)

NOTE: In general, most functions that operate on strings (such as str2double) also operate on cell arrays of strings.

Sign up to request clarification or add additional context in comments.

Comments

2

For the second call to cellfun with emptyIdx, don't specify the UniformOutput flag to be 0. Remove that option and it will create a logical vector that you can use to index into your cell array directly and you can remove entries.

As such, you would do this instead:

emptyIdx = cellfun(@isempty, numericIds);

Once you do this, you can use logical indexing to remove the affected rows:

ids(emptyIdx) = [];
vals(emptyIdx,:) = [];

Here's a running example:

>> ids = { '1'; '2'; 'A'; '4' }

ids = 

    '1'
    '2'
    'A'
    '4'

>> numericIds = cellfun(@str2num, ids, 'un', 0)

numericIds = 

    [1]
    [2]
    []
    [4]

>> emptyIdx = cellfun(@isempty, numericIds)

emptyIdx =

     0
     0
     1
     0

>> vals = { 11, 12, 13, 14, 15; 21, 22, 23, 24, 25; 31, 32, 33, 34, 35;, 41, 42, 43, 44, 45}

vals = 

    [11]    [12]    [13]    [14]    [15]
    [21]    [22]    [23]    [24]    [25]
    [31]    [32]    [33]    [34]    [35]
    [41]    [42]    [43]    [44]    [45]

>> vals(emptyIdx,:) = []

vals = 

    [11]    [12]    [13]    [14]    [15]
    [21]    [22]    [23]    [24]    [25]
    [41]    [42]    [43]    [44]    [45]

>> ids(emptyIdx) = []

ids = 

    '1'
    '2'
    '4'

1 Comment

Thanks a lot for taking the time to answer. It is good to see where I was going wrong, though I went with the non-cellfun answer in the end.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.