extracting the index of a certain character in a cell array - matlab

I have a cell array like this:
and I want to extract the index of 2 in this cell array so I used these lines of codes:
for i = 1:size(idx,1)
if idx{i,1} ~= []
index = i;
end
end
but the code doesn't work.I mean the debuger never enters if beacause it doesn't understand that 2 differs from [].why? and how do you suggest me to write the code?
note that the character will not always be 2 and it may occur in other indexes too.

To test if you variable is empty use ISEMPTY function.
To do it for all elements in a cell array you can use CELLFUN:
index = find(~cellfun(#isempty, idx));

In Matlab, [] means empty, thus:
for i = 1:size(idx,1)
if ~isempty(idx{i,1})
index = i;
end
end

Related

append element to array in for loop matlab

I have a matrix 10x500 and I want to discard every row which contains in the first 100 elements a value above 6. First I am trying to make an array with all the indexes of the row to discard. Here my code
idx_discard_trials = [];
for i = 1:size(data_matrix,1)
if any(data_matrix(i,1:100)>6)
idx_discard_trials = i;
end
end
However, at the end of the loop I get just the last index, not a list. Does anybody know how to append elements to an array using a for loop?
It's because you keep rewriting a single value, you need to append the values through idx_discard_trials(end+1) = i, for example.
You don't need a loop for this however, try the following:
data_matrix(any(data_matrix(:,1:100) > 6, 2),:) = []

Concatenating (sub)fields of structs in a cell array

I have a Matlab object, that is a cell array containting structs that have almost identical structures and I want to programmatically get a (sub)field of the structs of all cell array elements.
For example, we take test
test = {struct('a',struct('sub',1)), struct('a',struct('sub',2),'b',1)};
This will create a cell array with the following structure:
cell-element 1: a --> sub --> 1
cell-element 2: a --> sub --> 2
\-> b --> 1
It can be seen that the elements of test don't have the exact same structure, but similar. How can I get all values of the a.sub fields of the elements of the cell. I can obtain them in this specific problem with
acc=zeros(1,numel(test));
for ii=1:numel(test)
acc(ii) = test{ii}.a.sub;
end
but I can't quite get this method to work in a more general context (ie. having different fields).
You may want to use the function getfield:
%//Data to play with
test = {struct('a',struct('sub',1)), struct('a',struct('sub',2),'b',1)};
%//I'm interested in these nested fields
nested_fields = {'a', 'sub'};
%//Scan the cell array to retrieve the data array
acca = cellfun(#(x) getfield(x, nested_fields{:}), test);
In case your data cannot guarantee that all the elements are the same type and size, then you need to output a cell array instead:
%//Scan the cell array to retrieve the data cell array
accc = cellfun(#(x) getfield(x, nested_fields{:}), test, 'UniformOutput', false);
Later Edit
If one wants to use different sets of nested fields for each cell element then:
%//nested_fields list should have the same size as test
nested_fields = {{'a','sub'}, {'b'}};
accm = cellfun(#(x,y) getfield(x,y{:}), test, nested_fields, 'UniformOutput', false);
Edit: No need for recursion, as shown by #CST-link:s answer; the native getfield function can neatly unfold a cell array of fields as its second argument, e.g. getfield(foo{i}, fields{:}) instead of the call to the recursive function in my old answer below. I'll leave the recursive solution below, however, as it could have some value in the context of the question.
You can build you own recursive version of getField, taking a cell array of fields.
function value = getFieldRec(S,fields)
if numel(fields) == 1
value = getfield(S, fields{1});
else
S = getfield(S,fields{1})
fields{1} = [];
fields = fields(~cellfun('isempty',fields));
value = getFieldRec(S,fields);
end
end
Example usage:
foo = {struct('a',struct('sub',1)), ...
struct('a',struct('sub',2),'b',3), ...
struct('c',struct('bar',7),'u',5)};
accessFields = {'a.sub', 'b', 'c.bar'};
values = zeros(1,numel(foo));
for i = 1:numel(foo)
fields = strsplit(accessFields{i},'.');
values(i) = getFieldRec(foo{i},fields);
end
With the following result
values =
1 3 7
I have found a way to do this using eval:
function out = catCellStructSubField(cellStruct, fieldName)
out = zeros(1,numel(cellStruct));
for ii = 1:numel(cellStruct)
out(ii) = eval(['cellStruct{ii}.' fieldName]);
end
Where it can be used on my test example like this:
catCellStructSubField(test, 'a.sub')
Dynamic field names (cellStruct{ii}.(fieldName)) does not work because I'm accessing sub-fields.
I know eval is often a bad idea. I'm curious for different solutions.

Correct way of adding to a list from cell array in matlab?

I'm writing some code to split up a 180x2 matlab cell array based on a string in the second column. This string is one of EP,GA,PS,SS or SA. In python I could define empty lists then use conditionals to iterate over the elements of the list and append them to the relevant lists.
The Code
EP=[];
GA=[];
PS=[];
SA=[];
SS=[];
for i=1:size(d),
if strcmp(d(i,2),'EP'),
append(EP,d(i,1))
elseif strcmp(d(i,2),'GA'),
append(GA,i)
elseif strcmp(d(i,2),'PS'),
append(PS,i)
elseif strcmp(d(i,2),'SA'),
append(SA,i)
elseif strcmp(d(i,2),'SS'),
append(SS,i)
end
end
Note that 'd' is a 180x2 cell array that I copied and pasted into matlab rather than import. The general structure of the data however is:
12.9089000000000 'EP'
13.3697000000000 'SA'
13.4335000000000 'EP'
13.5302000000000 'PS'
13.8434000000000 'EP'
14.2583000000000 'EP'
14.8221000000000 'GA'
However when attempting this tactic in matlab I get an error:
Error using append (line 38)
Wrong number of input arguments for obsolete
matrix-based syntax.
Error in Boxplot_All_results (line 12)
append(GA,i)
Could somebody tell me the correct way of doing this in matlab
First of all, please not that d is a cell array. To index the elements of a cell array, use {}. If you index using () like you did, you end up with a small cell array containing only the indexed element(s).
To append in Matlab you basically have two choices:
%concatenate the list with a scalar. Also suitable for two lists.
EP=[EP,d{i,1}] %could also be done using cat
%append to the end
EP(end+1)=d{i,1}
While this fixes the problem, I recommend to implement it on a more generic way:
names={'EP','GA','PS','SA','SS'}
s=struct()
for idx=1:numel(names)
s.(names{idx})=[d{strcmpi(d(:,2),names{idx}),1}]
end
You end up with a struct containing the data you want.
Can you show MatLab code?
How do you append those values to cell array?
You can just create one a = {}
and then append element at the size+1 index. That operation extends your cell array.
Or you can also do a trick like that: a = [a; {value}]
To append elements to a cell array, a correct syntax would be:
for i=1:size(d),
if strcmp(d(i,2),'EP'),
EP = [EP ; d(i,1) ] ; %// append(EP,d(i,1))
elseif strcmp(d(i,2),'GA'),
GA = [GA ; d(i,1) ] ; %// append(GA,i)
but there are more ways, as you can read in the documentation: Add Cells to a Cell Array
There are also more ways to build your final extracted arrays in one assignment instead of having them growing dynamically (mLint will complain about that by the way).
Get the indices of the elements which satisfy your condition then create an array with only the matching elements. For example:
iEP = cellfun( #(c) strcmp(c,'EP') , d(:,2) ) ; %// logical array of indexes where the condition is true
EP = d(iEP,1) ; %// Create "EP" in one assignment - EP is a [cell] array
If you only have numeric values to retrieve in these new variables, may be having a double array instead of a cell array will be convenient :
iGA = cellfun( #(c) strcmp(c,'GA') , d(:,2) ) ; %// logical array of indexes where the condition is true
GA = cell2mat( d(iGA,1) ) ; %// Create "GA" in one assignment - GA is a [double] array
Of course you can bypass the intermediate variable holding the indices:
PS = d( cellfun(#(c)strcmp(c,'PS'),d(:,2)),1) ; %// Create "PS" in one assignment [cell] array
SA = cell2mat(d(cellfun(#(c)strcmp(c,'SA'),d(:,2)),1)) ; %// Create "SA" in one assignment [double] array

Scanning data from cell array and removing based on file extensions

I have a cell array that is a list of file names. I transposed them because I find that easier to work with. Now I am attempting to go through each line in each cell and remove the lines based on their file extension. Eventually, I want to use this list as file names to import data from. This is how I transpose the list
for i = 1:numel(F);
a = F(1,i);
b{i} = [a{:}'];
end;
The code I am using to try and read the data in each cell keeps giving me the error input must be of type double or string. Any ideas?
for i = 1:numel(b);
for k = 1:numel(b{1,i});
b(cellfun(textscan(b{1,i}(k,1),'%s.lbl',numel(b)),b))=[];
end;
end;
Thanks in advance.
EDIT: This is for MATLAB. Should have been clear on that. Thanks Brian.
EDIT2: whos for F is
Name Size Bytes Class Attributes
b 1x11 13986188 cell
while for a is
Name Size Bytes Class Attributes
a 1x1 118408 cell
From your description I am not certain how your F array looks, but assuming
F = {'file1.ext1', 'file2.ext2', 'file3.ext2', 'file2.ext1'};
you could remove all files ending with .ext2 like this:
F = F(cellfun('isempty', regexpi(F, '\.ext2$')));
regexpi, which operates on each element in the cell array, returns [] for all files not matching the expression. The cellfun call converts the cell array to a logical array with false at positions corresponding to files ending with .ext2and true for all others. The resulting array may be used as a logical index to F that returns the files that should be kept.
You're using cellfun wrong. It's signature is [A1,...,Am] = cellfun(func,C1,...,Cn). It takes a function as first argument, but you're passing it the result of textscan, which is a cell array of the matching strings. The second argument is a cell array as it should be, but it doesn't make sense to call it over and over in a loop. `cellfunĀ“'s job is to write the loop for you when you want to do the same thing to every cell in a cell array.
Instead of parsing the filename yourself with textscan, I suggest you use fileparts
Since you're already looping over the cell array in transpose-step, it might make sense to do the filtering there. It might look something like this:
for i = 1:numel(F);
a = F(1,i);
[~,~,ext] = fileparts(a{:});
if strcmpi(ext, '.lbl')
b{i} = [a{:}'];
end
end;

Iterating through struct fieldnames in MATLAB

My question is easily summarized as: "Why does the following not work?"
teststruct = struct('a',3,'b',5,'c',9)
fields = fieldnames(teststruct)
for i=1:numel(fields)
fields(i)
teststruct.(fields(i))
end
output:
ans = 'a'
??? Argument to dynamic structure reference must evaluate to a valid field name.
Especially since teststruct.('a') does work. And fields(i) prints out ans = 'a'.
I can't get my head around it.
You have to use curly braces ({}) to access fields, since the fieldnames function returns a cell array of strings:
for i = 1:numel(fields)
teststruct.(fields{i})
end
Using parentheses to access data in your cell array will just return another cell array, which is displayed differently from a character array:
>> fields(1) % Get the first cell of the cell array
ans =
'a' % This is how the 1-element cell array is displayed
>> fields{1} % Get the contents of the first cell of the cell array
ans =
a % This is how the single character is displayed
Since fields or fns are cell arrays, you have to index with curly brackets {} in order to access the contents of the cell, i.e. the string.
Note that instead of looping over a number, you can also loop over fields directly, making use of a neat Matlab features that lets you loop through any array. The iteration variable takes on the value of each column of the array.
teststruct = struct('a',3,'b',5,'c',9)
fields = fieldnames(teststruct)
for fn=fields'
fn
%# since fn is a 1-by-1 cell array, you still need to index into it, unfortunately
teststruct.(fn{1})
end
Your fns is a cellstr array. You need to index in to it with {} instead of () to get the single string out as char.
fns{i}
teststruct.(fns{i})
Indexing in to it with () returns a 1-long cellstr array, which isn't the same format as the char array that the ".(name)" dynamic field reference wants. The formatting, especially in the display output, can be confusing. To see the difference, try this.
name_as_char = 'a'
name_as_cellstr = {'a'}
You can use the for each toolbox from http://www.mathworks.com/matlabcentral/fileexchange/48729-for-each.
>> signal
signal =
sin: {{1x1x25 cell} {1x1x25 cell}}
cos: {{1x1x25 cell} {1x1x25 cell}}
>> each(fieldnames(signal))
ans =
CellIterator with properties:
NumberOfIterations: 2.0000e+000
Usage:
for bridge = each(fieldnames(signal))
signal.(bridge) = rand(10);
end
I like it very much. Credit of course go to Jeremy Hughes who developed the toolbox.