How do I access and edit a cell array using a double for indexes?

29 views (last 30 days)
Hi everyone,
working on some data, I came across a topic I avoided since starting with Matlab half a year ago. It's about indexing, accessing and editing data in a cell array. For example I got a 300000x1 cell array 'results' filled with 50 city names stored in a 50x1 cell named 'cities'. So each cell of 'results' contains one of the 50 names. What I want to do, is replacing the names in 'results' with their position/index in 'cities', in order to turn it into a double array and to save computing time for following tasks. I tried the following.
for k=1:length(cities)
cells = find(ismember(results,cities(k,1)));
results(cells) = k;
end;
Wich just produces the error Conversion to cell from double is not possible. I tried this because cells contains the indexes in 'results' of the just called city (cities(k,1)) And i thought this way I could also edit the values, which is obviously not possible.
My workaround would be the combination of 2 for loops, which is, regarding the length of the 'results' arrays, pretty slow.
for k=1:length(cities)
cells = find(ismember(results,cities(k,1)));
for n=1:length(cells)
results{cells(n,1),1} = num2str(k); %num2str because otherwise k-loop would not work for k>=2
end;
end;
% cellfun(@str2num, results(:,1)) in the end to convert the strings to num
But how do I get the first solution to work? How to I access the cell array correctly with a double as indexing? And is the first way really faster than the 'loop-Way'?
Many thanks in advance!
Best regards!

Accepted Answer

Stephen23
Stephen23 on 26 Nov 2015
Edited: Stephen23 on 26 Nov 2015
Note that you cannot "turn it into a double array": you can only reassign variable names to a new variable, but this would completely replace the old cell array.
The basic problem with your first loop is there is some confusion about cell array indexing: you try to allocate a double to a cell, thus the error. If you had put the double inside the cell then it would have worked:
for k = 1:numel(cities)
idx = ismember(results,cities(k,1));
results{idx} = k;
end
Cell array indexing in a nutshell:
  • parentheses () refer to the cells themselves.
  • curly braces {} refer to the contents of the cells.
So given that results is a cell array, and k is a double, your line results(cells) = k tries to allocate the double to the cell itself, whereas what you needed to do was allocate it to the contents of the cell using curly braces: results{cells} = k.
Easiest Solution
The easiest solution is to use the second output from ismember:
>> cities = {'london','berlin','paris'};
>> results = {'berlin','paris','paris','london','paris','london','berlin','london'};
>> [~,LocB] = ismember(results,cities)
LocB =
2 3 3 1 3 1 2 1
Alternative Solution
If your really want to do this in a loop:
>> out = nan(1,numel(results));
>> for k = 1:numel(cities), out(strcmp(results,cities{k})) = k; end
>> out
out =
2 3 3 1 3 1 2 1
Note that we loop over the smaller cell array cities, not the larger one results, and we use logical indexing rather than using slow find.
  1 Comment
Mr Anderson
Mr Anderson on 26 Nov 2015
Edited: Mr Anderson on 26 Nov 2015
thanks for your answer! but if i try your solution, this error pops up
The right hand side of this assignment has too few values to satisfy the left hand side.
EDIT:
Creating a completely new array would be fine for me, but even if doing so, i still would not know how to use the logical, or double index correctly :(
EDIT2
Thank you very much! I didnt even think about strcmp, but its the easiest way, since strcmp compares the cities{k} string with the whole results array and creates the logical to access the cells or to create a new array out
Thank you so much for helping me! :)

Sign in to comment.

More Answers (1)

Thorsten
Thorsten on 26 Nov 2015
Edited: Thorsten on 26 Nov 2015
results2 = cellfun(@(c) find(ismember(cities, c)), results);
  1 Comment
Mr Anderson
Mr Anderson on 26 Nov 2015
If i try this, this error shows up
Error using cellfun Non-scalar in Uniform output, at index 15, output 1. Set 'UniformOutput' to false

Sign in to comment.

Products

Community Treasure Hunt

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

Start Hunting!