So I've got a struct, settings, which contains three fields, averageValue, heightLabels and heights.
settings.averageValue = 7.5121 7.2742 7.4602
settings.heights = 105.1000 105.2000 105.3000
I'm looping through these with the following code:
for m = 1:length(settings.averageValue)
settings.heightLabels(m) = {sprintf{'%.1f %s', settings.heights(m), 'm')};
end
However, I get the error "Conversion to char from cell is not possible.". Any ideas?
Well, I get your question now. Let's say you have variables A,B,C,D which you want to club together in a struct variable. Here's how you do it:
settings.A = A;
settings.B = B;
settings.C = C;
settings.D = D;
settings is a struct variable now, and if you want to access A, you refer to it as:
disp(settings.A) %display A
settings.A = 10; %edit A
newA = settings.A; %assign A to a new variable
Pass settings to a function, do whatever.
Okay guys I figured it out. It was a datatype question; my struct field was supposed to be a cell but it was a string. Rather embarrassing.
I resolved the problem with the following code when creating the struct fields:
settings.averageValue = {};
settings.heightLabels = {};
Thanks for your help!
Related
I'm trying to automate a process for getting information out of an array of structs.
I have the following code:
function [data] = extractData(struct,str)
data = {};
for i = 1:length(struct)
data{i} = struct(i).str;
end
The problem is that I want to provide the str value referring to a pre-determined field. In it's current form, it won't accept str and say "str is an unknown field."
The easiest way to do this would to use:
function data = extractData(struct)
str = fieldnames(struct);
data = {};
for i = 1:numel(str)
data{i} = struct.(str{i});
end
end
You may also want to consider a few different things here. First, you may want to change the name of your struct to a different name as was said above. Also you might want to look into cell arrays. Cell arrays can hold variables of different types and lengths and are easier you use.
I am aware many of you will think this should be easily solvable. However, I have no clue about MATLAB.
Here goes my problem: when trying to execute the following example in the Command Window through the command
getLogReturnExcel('ALL.xls', {'ALL'}, 37000, 38000)
the cell-type error appears for this function. From what I understand however, when using {} the function should be grabbing the type inside {} (String in this case?) instead of the cell itself, which would be being grabbed if we were to use (), so there should be no error? Or is there something much more elementary that I might be overseeing? Thanks in advance for every bit of help; as you can tell I very much need it.
Cheers,
Ben
Here goes the function getLogReturnExcel:
function [logreturn, datearray] = getLogReturnExcel( datafilename, ticker, begindate, enddate )
[aanumber, aatext] = xlsread(datafilename);
aaticker = aatext(:,1);
aadate = aanumber(:,2);
aaret = zeros(length(aaticker),1);
aaret(1,1) = 0;
for i = 2:length(aaret)
aaret(i,1) = ln(aanumber(i,3))-ln(aanumber(i-1,3));
end
aadate = aadate(strcmp(aaticker,ticker));
aaret = aaret(strcmp(aaticker,ticker));
logreturn = aaret(aadate>=begindate & aadate<=enddate);
datearray = aadate(aadate>=begindate & aadate<=enddate);
return
The file 'ALL.xls' contains 3 columns, one with strings (the acronym for stocks) and two with numbers (I'm assuming double), one for the date in Excel-format and one with each day's stock standing.
The string can be obtained by using:
ticker{:}
or else the comparison in the lines
aadate = aadate(strcmp(aaticker,ticker));
aaret = aaret(strcmp(aaticker,ticker));
will be between strings and cell array.
Here is some documentation to access elements of a cell array.
I am trying to cycle through a list of variables I have say 30+ and calculate the maximum and minimum value for each column in each variable. Save this in a new array and then export to excel.
My thoughts were to use the who function to create an array with the name of all variables which are present. Then cycling through each one using a for loop after working out the size of the array which was created. This works fine, however when I try and use the string to reference the array it does not work.
I will add in the code which I have written hopefully someone will be able to come up with an easy solution :).
variable_list = who
cell2 = input('What cell size do you want to look at? ');
STARTcell = input('What was the start cell size? ');
[num_variables, temp] = size(variable_list);
for va = 1:num_variables
variable = variable_list{va}
[max_value, max_index] = max(variable{cell2/STARTcell})
[min_value, min_index] = min(variable{cell2/STARTcell})
format_values{va} = vertcat(max_values, max_index, min_value, min_index);
end
The variables I am looking at are arrays which is why I use the cell2/STARTcell to reference them.
You need to use the eval() function to be able to get the value of a variable corresponding to a string. For example:
a = 1;
b = 2;
variable_list = who;
c = eval(variable_list{2});
results in c being 2. In your code, the following line needs to change from:
variable = variable_list{va}
to:
variable = eval(variable_list{va});
resulting in variable having the value of the variable indicated by the string variable_list{va}. If variable is of cell type, then you should be fine, otherwise you may have to revise the next two lines of code as well because it seems that you are trying to access the content of a cell.
Using a combination of this question and this Mathworks help thing on comma sep. lists I came up with this ugly way to make my formatting arguments a little prettier:
formatting{1,1} = 'color'; formatting{2,1} = 'black';
formatting{1,2} = 'fontweight'; formatting{2,2} = 'bold';
formatting{1,3} = 'fontsize'; formatting{2,3} = 24;
xlabel('Distance', formatting{:});
But it's still kinda ugly...is there a way to unpack a structure into a bunch of arguments a la a Python dictionary to **kwargs?
For instance, if I had the (IMHO) cleaner structure:
formatting = struct()
formatting.color = 'black';
formatting.fontweight = 'bold';
formatting.fontsize = 24;
Can I just pass that in somehow? If I try directly (xlabel('blah', formatting), or formatting{:}, it craps out saying "Wrong number of arguments".
You are very close. Just switch to a 1-D cell array.
formatting = {'Color', 'Red', 'LineWidth', 10};
figure
plot(rand(1,10), formatting{:})
If you really want to use a struct for formatting arguments, you can unpack it to a cell array and use it like above.
formattingStruct = struct();
formattingStruct.color = 'black';
formattingStruct.fontweight = 'bold';
formattingStruct.fontsize = 24;
fn = fieldnames(formattingStruct);
formattingCell = {};
for i = 1:length(fn)
formattingCell = {formattingCell{:}, fn{i}, formattingStruct.(fn{i})};
end
plot(rand(1,10), formatting{:})
It's probably a good idea to do the struct unpacking a separate little function so you can reuse it easily.
You can convert your structure to cell array with this function:
function c = struct2opt(s)
fname = fieldnames(s);
fval = struct2cell(s);
c = [fname, fval]';
c = c(:);
Then
formatting = struct2opt(formattingStructure);
xlabel('Distance', formatting{:});
I am collecting data from a process in a struct as follows;
timepace(1,i) = struct(...
'stageNo',str2num(stageNo), ...
'split1', splits(1,1),...
'split2', splits(1,2),...
'split3', splits(1,3) );
However, the number of “splits” is can vary from 2 to 10. At the moment I am using a longer code than shown above to allocate all the “splits” and if not, put a 0. But this makes me create a lot of unused data for the “just in case” situation of having so many splits.
Would there be a way to make the length of it flexible? I know the required final number because it is an input to the system for each query that I do.
Any ideas on how to make it flexible and related to a length variable?
You could use something like
S = struct('stageNo',str2num(stageNo));
for jj = 1:size(splits,2)
S.(['split' num2str(jj)]) = splits(1,jj);
end
timepace(1,i) = S;
It's called "dynamic field reference". You can find more information here for instance.
Just use an array instead of struct:
timepace(1,i) = struct(...
'stageNo',str2num(stageNo), ...
'split', *PUT HERE YOUR ARRAY*...
);
Don't forget that in the case of cell array, you need additional {} brackets.
timepace(1,i) = struct(...
'stageNo',str2num(stageNo), ...
'split', {{1,2,3,4,5}}...
);
If you must use struct than see Rodys answer.
You could also use cell2struct:
labels = {'split1','split2','split3',...}
c = num2cell(splits);
f = labels(1:numel(c));
s = cell2struct(c,f,2);