MATLAB:"matrix index is out of range for deletion" - matlab

I have a data structure that has a cell array "mydata", which has 250 rows of cells that look like this:
{1x1 cell}
{1x2 cell}
{1x4 cell}
{1x1 cell}
.
.
.
I want to have separate files which are only 1x1, but at the same time. I don't wanna change the length of my cell array and instead want to find a way to pass any extra component to new files and if there is nothing extra, it becomes an empty cell.For example, if one cell is 1x2 with cells like "rose" and "blue", in one file I wanna have "rose" and in the other file, "blue" to be saved.
I get "matrix index is out of range for deletion" for the following script. What is the issue in it? Is there any more straightfoward way to do what I want?
Part of what I've done:
mydata= structure.mydata;
first_file = cell(numel(mydata),1);
second_file = cell(numel(mydata),1);
for i = 1 : length(structure.mydata)
content = structure.mydata(i);
first_file(i) = content(1);
if length(content) > 1
second_file(i) = content(2);
else
second_file(i) = [];
end
end

Related

Textscan and Regexp Cell Data Layout

I'm trying to make some logic work with some legacy matlab code. I figured the easist thing was to make the data look the same as what the code is expecting.
I'm reading the relevant data from a CSV file, it's pretty simple -- but the format for the IDs changed from a simple number to an ID of the form [YY,ZZZZ].
As an example, the 'previous' CSV data looked like:
1,Simple,Data
2,More,Data-Dash-Data
3,Even,More
4,Really,More
The 'new' CSV data looks like:
[01,0001],Simple,Data
[02,1001],More,Data-Dash-Data
[03,9876],Even,More
[04,1234],Really,More
Previously, to read in the data, this logic was used:
fid = fopen(fileName);
data = textscan(fid,'%s%s%s%*s','Delimiter',',');
When this was done against the 'previous' CSV data, it returned data that look like this:
data =
1×3 cell array
{4×1 cell} {4×1 cell} {4×1 cell}
The cells then look like:
K>> data{:}
ans =
4×1 cell array
'1'
'2'
'3'
'4'
ans =
4×1 cell array
'Simple'
'More'
'Even'
'Data'
ans =
4×1 cell array
'Data'
'Data-Dash-Data'
'More'
'Data'
So to handle the ID of the form [YY,ZZZZ], I had to modify the 'textscan' logic to handle the new ID format that we're using. To do that, I'm using a regexp function:
fid = fopen(fileName);
rawData = textscan(fid,'%s','Delimiter','\n');
data = regexp(rawData{1},'[ \-\/\w]*([\[][^\)\]]*[\]])?', 'match')
This then, after it reads in the data, gives me data that is formatted like this:
K>> data
data =
4×1 cell array
{1×3 cell}
{1×3 cell}
{1×3 cell}
{1×3 cell}
K>> data{:}
ans =
1×3 cell array
'[01,0001]' 'Simple' 'Data'
ans =
1×3 cell array
'[02,1001]' 'More' 'Data-Dash-Data'
ans =
1×3 cell array
'[03,9876]' 'Even' 'More'
ans =
1×3 cell array
'[04,1234]' 'Really' 'More'
So you can see that it has the correct data in it -- but the data is laid out differently which is breaking on the legacy code. So my question is how can I make the 'new' data be laid out like this as it was coming out of the 'textscan' logic:
data =
1×3 cell array
{4×1 cell} {4×1 cell} {4×1 cell}
You can use fileread to read in the raw file directly. Afterwards, you can use a regex which splits on either a comma, not followed by a digit, or on a carriage return.
c = regexp(fileread(fileName),',(?!\d)|\r\n','split');
formattedData = {c(1:3:end)',c(2:3:end)',c(3:3:end)'};
>> formattedData
formattedData =
1×3 cell array
{4×1 cell} {4×1 cell} {4×1 cell}

Size of a {mxn} cell in Matlab

When I create a cell from a text file and print it I get:
params =
{4x1 cell}
However when I use:
size(X)
I get:
1 1
So what can I use to see the size of the cell (I'm trying to get the size(in this case 4) of the cell to use in a loop).
If it's always going to be a 1x1 cell, then you can do
size(X{1})
If not you could do
s = cellfun(#size, X, 'uni', 0);
s{:}

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)
.....

Convert cells inside a cell array to cell arrays - 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}

how to sort a cell array which includes arrays?

I would like to sort a cell array according to one of the columns. The array is created by textscan function. There are some answers on web, but I still cannot get it working. I have the following array:
>> DATA
DATA =
{303427x1 cell} {303427x1 cell} {303427x1 cell} {303427x1 cell} [303427x1 uint32] [303427x1 double] [303427x1 uint32] [303427x1 int32] {303427x1 cell}
Important is the sixth column, which are times converted by datenum function. I want to sort the whole DATA by this column but with the link to another columns.
Normal sort or sortrows doesnt work for me. Could you help me please?
I take it you want to sort within each cell of DATA, correct? The datenum function produces serial time stamps since "year zero," so they can be sorted normally.
times = DATA{6};
[~,idx] = sort(times,'ascend');
for i=1:length(DATA)
DATA{i} = DATA{i}(idx);
end
You can avoid for-loop in #reve_etrange's answer by using CELLFUN after you get the sorting index idx.
DATA = cellfun(#(x) x(idx), DATA, 'UniformOutput', false);