What is the difference between [ ] and an empty array? - matlab

For example I have a 1x5 string array. Now I saw some fields are []. What does this mean? And what is the difference between a field which is totally empty?
How can I create such fields?
array(1)=[];
array(2)=;
%or
array(3)="";
And how can I check if the input of a field is empty, NaN or ""?

array(1)=[]; means that you're removing the first element of array if the variable already exists.
array(2)=; is an invalid expression.
array(3)="" stores an empty string "" at the third index of array. Since first two indices were not initialized by you in your code snippet, so these two indices will store <missing>. If you had an array of double class, you would have got zeros instead of <missing>. Presence of <missing> can be checked by ismissing.
In a string array, you cannot have Nan or empty. You can have "" string though.
You can have those elements if you have a cell array instead.
array{1} = [];
array{2} = "";
array{3} = NaN;
Now presence of [], "", and NaN in the above cell array can be checked by isempty, strcmp and isnan respectively with cellfun.

Related

How to empty a cell

I have a cell array that contains a lot of NaN. But for whatever reason the isnan function can't detect them (hence this doesn't work cellfun(#(Iarray) any(isnan(Iarray)),Iarray);) so I figured it was actually strings that contains NaN.
I perform two things on this array : cleaning empty rows and columns and removing NaN (well trying to).
So I want to replace all the NaN by empty cells and then perform to clean all empty cells with the isempty function. I'll use a loop and if char(x(i,j))=='NaN'.
So here comes my problem I want to empty a cell and then detect that cell with the isempty function but I have no idea how. I have tried x(1,2)= [], x(1,2)= {[]}, x(1,2)='' but none of those gives a 1 for isempty(x(1,2)) for example.
Does anyone know how to solve my problem?
Thanks in advance!
If you want to empty the content of a cell you can use :
x{1,2} = [];
There is a difference between indexing using parentheses () and brackets {}. You can think a cell array as an array of cells that each cell contains a value such as 1 ,2 , []. When a cell is indexed with parentheses it returns the result as cell (or more precisely as an array of type cell) but when it is indexed with brackets it returns the content of the cell (or more precisely as a comma separated list containing the contents of the indexed cells). So when you write such an expression:
x(1,2) = [];
It removes the second element from the array of cells and behaves like indexing other array types. For example when you want to remove the second element of a = [1 2 3] you can use a(2)=[].
But when you write x{1,2} = []; it accesses the content of the cell and sets it to a null array [0 x 0] of type double that is empty.
Likewise a={} is a [0 x 0] null array of cells and b={[]} is an [1 x 1] array of cells that its first element contains a null array [0 x 0] of type double. When you use isempty(b) it returns false because it contains an element and when you use isempty(b(1)) it returns false because b(1) returns an array of cells that contains an element but when you use isempty(b{1}) it returns true because the {} operator extracts the contents of the first cell that is a null array.
In short, cells can be accessed using both () and {}, and based on the situation [] has different functionalities: a) removing element b) null array.

How to find all values greater than 0 in a cell array in Matlab

I want to find and save all values greater than 0 in an array and save them in a variable called "times". How do I do that? And what is the difference between saving the indices of those cells versus the actual values of the cells?
This is what I have tried, but it must be worng because I get the error:
Undefined operator '>' for input arguments of type
'cell'.
clear all, close all
[num,txt,raw] = xlsread('test.xlsx');
times = find(raw(:,5)>0)
To access the contents of a cell you must use {} instead of ():
idx = find([raw{:, 5}] > 0);
But this gives you the index of the cells of raw containing a positive value. If you want the values instead, you can access them and collect them in a numeric array in this way:
times = [raw{idx, 5}];

MATLAB: removing non-unique numbers from a field within a structure

I have a structure in Matlab, each field contains elements with varying numbers of variables. I would like to remove duplicates of numbers that appear within the same field: I know the unique() function and know how to use it to scan through fields one at a time but not an entire field.
I think I want something like:
structure(1:length(structure)).field=unique(structure(1:length(structure)).field
and get
original
field=[1,2,3] [1,4,5] [2,5,8]
to turn into
field=[1,2,3] [4,5] [8]
Maybe a complicated for loop similar to below (isn't working) which would grab the values from the first element in the field, search through each additional element, and if that value is present set it equal to =[];, and iterate through that way?
for n=1:length(RESULTS)
for m=1:length(RESULTS(n).Volumes)
for l=1:length(RESULTS)
for o=1:length(RESULTS(l).Volumes)
if RESULTS(n).Volumes(m)==RESULTS(l).Volumes(o)
RESULTS(l).Volumes(o)=[];
end
end
end
end
end
Thanks!
This is a quick-and-dirty attempt, but you might be able to improve on it. Assume your struct array and field are sa(:).v. I'm also assuming that the field contains a 1xn array of numbers, as in your example. First, make a "joint" array with the concatenation of all field values and filter the non-unique values:
joint = cell2mat({sa.v});
[uniqJoint,~,backIdx] = unique(joint);
The "uniqJoint" array has also been sorted, but the "backIdx" array contains the indices that, if applied to uniqJoint, will rebuild the original "joint" array. We need to somehow connect those to the original indices (i,j) into the struct array and within the field value sa(i).v(j). To do that, I tried creating an array of the same size as "joint" that contains the indices of the struct that originally had the corresponding element in the "joint" array:
saIdx = cell2mat(arrayfun(#(i) i * ones(1,length(sa(i).v)), ...
1:length(sa), 'UniformOutput', false));
Then you can edit (or, in my case, copy and modify the copy of) the struct array to set the field to the values that have not appeared before. To do that, I keep a logical array to mark the indices of "backIdx" as "already used", in which case I skip those values when rebuilding the fields of each struct:
sb = sa;
used = false(length(backIdx));
for i = 1:length(sa)
origInd = find(saIdx == i); % Which indices into backIdx correspond to this struct?
newInd = []; % Which indices will be used?
for curI = backIdx(origInd)
if ~used(curI)
% Mark as used and add to the "to copy" list
used(curI) = true;
newInd(end+1) = curI;
end
end
% Rewrite the field with only the indices that were not used before
sb(i).v = uniqJoint(newInd);
end
In the end, the data in sb(i).v contains the same numbers as sa(i).v without repeats, and removing those that appeared in any previous elements of the struct.

Array of struct: set all empty attributes ([]) to NaN

I have an array of structs and would like to set all empty attributes to NaN:
structArray =
29x1 struct array with fields:
value
id
How do I set all struct.value attributes to NaN, if they are empty?
If they are empty the conversion [structArray.value] omits the empty elements...
Given this:
x(29).id = [];
x(29).value = [];
You can set the value of all .id fields like this
[x.value] = deal(nan);
To set only a particular subset of values define a mask of values to set and then use it in your assignment statement:
maskEmptyId = arrayfun( #(a)isempty(a.id), x );
[x(maskEmptyId).id] = deal(nan);
As #Pursuit explained there is an excellent way to replace the empty fields with NaNs
However, you may also be interested in a different approach.
Instead of replacement in hindsight you may be able to prevent the empty spots to occur in the first place. Assuming they are empty because nothing has been assigned to them, you can simply initialize your struct with NaNs.
For example:
structArray = struct ('id',[],'value',NaN)
Calling this before you assign anything to structArray would initialize the value field with NaN, but will still initialize the id to be empty.

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.