Convert cells inside a cell array to cell arrays - matlab - matlab

Do not get confused with row numbers in the arrays. I am just asking converting 1 into style 2
This is Cell Array C
I want to convert it to the below version how can i do that ?
V2 =

If I understand correctly, you have a flat cell array of strings (which contain valid MATLAB cell array definitions), and you want to convert each string into a sub-cell-array of its own. So what you need is:
cellfun(#eval, C, 'UniformOutput', false)
Where C is the original cell array of strings.
Example:
C = {'{''samsung'', ''n150'', ''jp0xtr'', ''n570''};'; ...
'{''samsung'', ''n150'', ''jp0xtr'', ''beyaz''};'}
C2 = cellfun(#eval, C, 'UniformOutput', false)
The result is:
C =
'{'samsung', 'n150', 'jp0xtr', 'n570'};'
'{'samsung', 'n150', 'jp0xtr', 'beyaz'};'
C2 =
{1x4 cell}
{1x4 cell}

Related

Assign to subset of cell array - MATLAB

I'm trying to assign a cell array to a subset of another cell array, like
data_date1 = '08/15/2003';
data_date2 = '08/16/2003';
data_date3 = '08/17/2003';
num1 = 56;
num2 = 23;
num3 = 2;
cell_1={data_date1, num1; data_date2, num2};
array=cell(3,1)
array{1:2} = cell_1 % problem line
array{3} = {data_date3, num3}
For context, the cell_1 array is the output of another function, and I'm trying to fill array in a loop in another function.
What's the proper method for this?
To copy cell array elements from one cell array to another without having to access the content of the element you can use the standard matrix indexing syntax, which uses the brackets (i,j) instead of the curly braces {i,j}.
let M be a cell array:
M(i,j) return a 1x1 cell, copy of the (i,j) element of M
M{i,j} return the content of the (i,j)th element of M. This could be of any type, depending on what the cell content was.
Cell array as a standard array
So in your case you can assign subarray to a larger array, but you just have to watch your indexing (the size in all dimensions should be correct).
So if you declare a 3x2 cell array:
array=cell(3,2)
Then you can assign your 2x2 sub array to it, if you have the address right:
>> array(1:2,:) = cell_1
array =
'08/15/2003' [56]
'08/16/2003' [23]
[] []
And then add your last elements:
>> array(3,:) = {data_date3, num3}
array =
'08/15/2003' [56]
'08/16/2003' [23]
'08/17/2003' [ 2]
This way treat your array like an nxm standard array, just consider the cell type like a specific type (like you would have double or uint8 array) without having to know the type of the data they contain inside.
Nested Cell array
Cell array have this capacity to be nested. So a single cell of a cell array could contain another whole cell array (where each cell could contain cell array etc ... although I wouldn't recommend nesting too deep).
In this configuration, you final array could be as you defined it, a 3x1 cell array, where each cell would contain another 1x2 cell array. You can also assign subarray to this type, but again the sizes of source and destinations have to match. So if you prefer this form, you would have to define your cell_1 slightly differently:
>> cell_1= { {data_date1, num1} ; { data_date2, num2} }
cell_1 =
{1x2 cell}
{1x2 cell}
Note the nesting of cell array into the larger cell array, in order to have a 1x2 subarray, which you can now assign to your main array:
>> array=cell(3,1) ;
array(1:2) = cell_1
array =
{1x2 cell}
{1x2 cell}
[]
Now to add the last element you have two different ways but you need to be careful:
array(3) = { {data_date3, num3} } %// assign a 1x2 sub array to the 3rd element of "array"
array{3} = {data_date3, num3} %// set the content of the 3rd element of "array" as a 1x2 cell array
These two lines are equivalent, they produce the same result. You can do either or, depending on the style you prefer (or may be forced by the shape your data are coming in).
There is error is because you cannot use indexing with cell array like that. Either you must do like:
array{1} = cell_1;
array{2} = cell_1;
array{3} = {data_date3, num3};
or you can try repmat (no need initialization array = cell(3,1)), though I don't know how long is your array:
array = repmat({cell_1}, 2, 1);
% or: array = {cell_1; cell_1}
array{3} = {data_date3, num3};
Another way if array is short:
array = {cell_1; cell_1; {data_date3, num3}};

Matlab Array has strange syntax

In Matlab, we use textscan to get a cell array from a file or somewhere. But the behavior of the cell array is so strange.
There is the sample code:
>> str = '0.41 8.24 3.57 6.24 9.27';
>> C = textscan(str, '%3.1f %*1d');
>> C
C =
[5x1 double]
We can know that C is a cell array of size 5 * 1. When I use C{1}, C{1}{1} and C(1). I get the following result:
>> C{1}
ans =
0.4000
8.2000
3.5000
6.2000
9.2000
>> C{1}{1}
Cell contents reference from a non-cell array object.
>> C(1)
ans =
[5x1 double]
Why I cannot use C{1}{1} to get the element from the cell array ? Then how can I get the elements from that cell array ?
An example I found on the Internet is :
%% First import the words from the text file into a cell array
fid = fopen(filename);
words = textscan(fid, '%s');
%% Get rid of all the characters that are not letters or numbers
for i=1:numel(words{1,1})
ind = find(isstrprop(words{1,1}{i,1}, 'alphanum') == 0);
words{1,1}{i,1}(ind)=[];
end
As words{1,1}{i,1}(ind)=[] show, what is the mechanism of using {}?
Thanks
Then how can I get the elements from that cell array ?
C = C{:}; % or C = C{1};
Access values by C(1), C(2) and so on
There is a slightly different syntax for indexing into cell arrays and numerical arrays. Your output
>> C
C =
[5x1 double]
is telling you that what you have is a 1x1 cell array, and in that 1 cell is a 5x1 array of doubles. Cell arrays are indexed into with {}, while 'normal' arrays are indexed into with ().
So you want to index into the first element of the cell array, and then index down to the first value in the 5x1 array of doubles using C{1}(1). To get the second value - C{1}(2), and so forth.
If you're familiar with other programming languages, cell arrays are something like arrays of pointers; the operator A(n) is used to get the nth element of the array A, while A{n} gets the object pointed to by the nth element of the array A (or 'contained in the nth cell of cell array A'). If A is not a cell array, A{n} fails.
So, knowing that C is a cell array, here's why you got what you got in the cases you tried -
C{1} returns the 5x1 double array contained in the first cell of C.
C{1}{1} gets the object (call it B) contained in the first cell of C, and then tried to get the object contained in the first cell of B. It fails because B is not a cell array, it is a 5x1 double array.
And C(1) returns the first element of C, which is a single cell containing a 5x1 double array.
But C{1}(1) would get you the first element of the 5x1 array contained in the first cell of C, which is what you are looking for. As #Cheery above me noted, it's probably easier, instead of writing C{1}(1), C{1}(2), ... to remove the 'cell-level' indexing by setting C=C{1}, which means C is now a 5x1 double array, and you can get the elements of it using C(1), C(2), ... Hope that makes sense!

Read string from txt file and use string for loop

Trying to read a txt file, then to loop through all string of the txt file. Unfortunately not getting it to work.
fid = fopen(fullfile(source_dir, '1.txt'),'r')
read_current_item_cells = textscan(fid,'%s')
read_current_item = cell2mat(read_current_item_cells);
for i=1:length(read_current_item)
current_stock = read_current_item(i,1);
current_url = sprintf('http:/www.', current_item)
.....
I basically try to convert the cell arrays to a matrix as textscan outputs cell arrays. However now I get the message
Error using cell2mat (line 53) Cannot support cell arrays containing cell arrays or objects.
Any help is very much appreciated
That is the normal behaviour of textscan. It returns a cell array where each element of it is another cell OR array (depending on the specifier) containing the values corresponding to each format specifier in the format string you have passed to the function. For example, if 1.txt contains
appl 12
msft 23
running your code returns
>> read_current_item_cells
read_current_item_cells =
{4x1 cell}
>> read_current_item_cells{1}
ans =
'appl'
'12'
'msft'
'23'
which itself is another cell array:
>> iscell(read_current_item_cells{1})
ans =
1
and its elements can be accessed using
>> read_current_item_cells{1}{1}
ans =
appl
Now if you change the format from '%s' to '%s %d' you get
>> read_current_item_cells
read_current_item_cells =
{2x1 cell} [2x1 int32]
>> read_current_item_cells{1}
ans =
'appl'
'msft'
>> read_current_item_cells{2}
ans =
12
23
But the interesting part is that
>> iscell(read_current_item_cells{1})
ans =
1
>> iscell(read_current_item_cells{2})
ans =
0
That means the cell element corresponding to %s is turned into a cell array, while the one corresponding to %d is left as an array. Now since I do not know the exact format of the rows in your file, I guess you have one cell array with one element which in turn is another cell array containing all the elements in the table.
What can happen is that the data gets wrapped into a cell array of cell arrays, and to access the stored strings you need to index past the first array with
read_current_item_cells = read_current_item_cells{1};
Converting from cell2mat will not work if your strings are not equal in length, in which case you can use strvcat:
read_current_item = strvcat(read_current_item_cells{:});
Then you should be able to loop through the char array:
for ii=1:size(read_current_item,1)
current_stock = read_current_item(ii,:);
current_url = sprintf('http:/www.', current_stock)
.....

sort columns in Matlab

I have 2 columns of data imported from using textscan. The data looks like this where U is undetect and D is detect
mydata=
.51 U
.57 D
.48 U
.47 D
my data = [4x1 double] [4x1 char]
I want to sort the data by the first column and so the data would look like this
.47 D
.48 U
.51 U
.57 D
I would like to preserve the cell structure so that the following command to assign logical value still hold true:
c = zeros(size(mydata,1),1); % preallocate empty matrix
c = mydata{2} == 'U';
for i = 1:size(mydata,1)
curValue = mydata{i,2};
data{i,3} = ~isempty(curValue) && ischar(curValue) && strcmp(curValue ,'U');
end
I read about sortrows but the function is used to sort matrix containing just numbers.
Does anyone have a solution for sorting arrays with a mixture of numbers and characters.
You can SORT by one vector and apply the sorting index to another vector.
[mydata{1},idx] = sort(mydata{1});
mydata{2} = mydata{2}(idx);
I don't think you can directly sort the cell array, because each cell is considered a different "entity". You can always sort the numbers, use the indices to sort the characters, and then put it back in the cell array:
nums = mydata{1};
chars = mydata{2};
[~, ind] = sort(nums);
sortednums = nums(ind);
sortedchars = chars(ind);
mydata{1} = sortednums;
mydata{2} = sortedchars;

How does one concatenate cell arrays that are part of a cell array in MATLAB?

I have a cell array allData which is Nx1. Each cell contains a structure with a names property (the name is a custom object, but think of it as a cell array of strings if you like). I would like to create a single cell array that contains all of the names. For example, if N=3, so that allData is a 3x1 cell array, then the following would accomplish my goal:
A = allData{1};
B = allData{2};
C = allData{3};
allNames = [A.names B.names C.names];
The problem with this approach is that N is large and changes depending on the input, so I'm hoping that there is a clever way to do this using cellfun, but everything that I've tried fails (e.g. it doesn't work to do allNames = [cellfun(#(x) {x.names}, allData)];).
UPDATE: Thanks to the suggested solutions, I can get everything into one cell array where each cell contains a cell array. My goal here is to concatenate these. More or less, what I have is:
{A.names B.names C.names}
and what I want and cannot seem to get is
{A.names{1} A.names{2} ... A.names{end} B.names{1} ... B.names{end} ...}
SOLUTION:
I needed pieces of each answer below, so here's the solution that worked for me:
from Andrew Lazarus:
allNames = arrayfun(#(x) x.name, [allData{:}], 'UniformOutput', false);
then, from gnovice:
allNames = vertcat(allNames{:});
Thanks to both!!
There are a few more details about your cell contents that would be needed for a more general solution, but if the names property always returns a cell array of strings, and if your structures are all scalars (i.e. 1-by-1 structure arrays), then the following solution using CELLFUN, CHAR, and CELLSTR will give you an N-by-1 cell array of strings allNames containing all of your names:
allNames = cellfun(#(x) {char(x.names)},allData);
allNames = cellstr(char(allNames{:}));
And here's an example where allData contains three different structures:
>> allData{1} = struct('names',{{'hello'}},'junk',1:3);
>> allData{2} = struct('names',{{'hi' 'yo' 'hey' 'whassup'}});
>> allData{3} = struct('names',{{'howdy';'aloha'}},'junk',4);
>> allNames = cellfun(#(x) {char(x.names)},allData);
>> allNames = cellstr(char(allNames{:}))
allNames =
'hello'
'hi'
'yo'
'hey'
'whassup'
'howdy'
'aloha'
EDIT:
Generalizing to the case where the names property returns a cell array of objects, not necessarily strings, you can try this solution which reshapes each cell array into an M-by-1 cell array, then vertically concatenates all of them into an N-by-1 cell array of objects:
allNames = cellfun(#(x) {reshape(x.names,[],1)},allData);
allNames = vertcat(allNames{:});
Or, if you would rather end up with a 1-by-N cell array of objects, you can do this:
allNames = cellfun(#(x) {reshape(x.names,1,[])},allData);
allNames = [allNames{:}];
Try this
allNames = arrayfun(#(x) x.name, [allData{:}], 'UniformOutput', false)
Omit the UniformOutput vararg for straight concatenation. This gives a cell output.