Calculations in table based on variable names in matlab - matlab

I am trying to find a better solution to calculation using data stored in table. I have a large table with many variables (100+) from which I select smaller sub-table with only two observations and their difference for smaller selection of variables. Thus, the resulting table looks for example similarly to this:
air bbs bri
_________ ________ _________
test1 12.451 0.549 3.6987
test2 10.2 0.47 3.99
diff 2.251 0.078999 -0.29132
Now, I need to multiply the ‘diff’ row with various coefficients that differ between variables. I can get the same result with the following code:
T(4,:) = array2table([T.air(3)*0.2*0.25, T.bbs(3)*0.1*0.25, T.bri(3)*0.7*0.6/2]);
However, I need more flexible solution since the selection of variables will differ between applications. I was thinking that better solution might be using either varfun or rowfun and speficic function that would assign correct coefficients/equations based on variable names:
T(4,:) = varfun(#func, T(3,:), 'InputVariables', {'air' 'bbs' 'bri'});
or
T(4,:) = rowfun(#func, T(3,:), 'OutputVariableNames', T.Properties.VariableNames);
However, the current solution I have is similarly inflexible as the basic calculation above:
function [air_out, bbs_out, bri_out] = func(air, bbs, bri)
air_out = air*0.2*0.25;
bbs_out = bbs*0.1*0.25;
bri_out = bri*0.7*0.6/2;
since I need to define every input/output variable. What I need is to assign in the function coefficients/equations for every variable and the ability of the function to apply it only to the variables that are present in the specific sub-table.
Any suggestions?

Related

How to create a variable in Matlab where certain subjects are coded as 1?

I want to create a variable called 'flag_artifact' where certain subjects from my dataset (for whom I know have bad quality images) are coded as e.g., 1. My dataset is stored in a table T with a certain number of rows and 'subject' is the 1st column in the table.
I managed to do it by creating a for loop. Surely there is a more efficient way to do this by perhaps directly creating the variable and using less lines of code? Could anyone give some advice?
Thank you very much! Here is what I have:
flag_artifact = {'T_300'}; %flagging subject number 300 for example
for i = 1:size(T,1)
if isequal(table2cell(T(i, 1)), flag_artifact)
T(i, 1) = {'1'};
end
end
However, when creating the variable flag_artifact = {'T_300'}, I would like it to include more than one subject. I tried using flag_artifact = {'T_300'}; {'T_301'}, as well as flag_artifact = {'T_300', 'T_301'} but it doesn't work because these subject identifiers do not get replaced with 1s.

FMU 2.0 interaction - requires parallel "container" for parameter values etc?

I work with pyfmi in Jupyter notebooks to run simulations and I like to work interactively and evaluate incremental changes in parameters etc. Long time ago I found it necessary to introduce a dictionary that work as a "container" for parameter and initial values. Now I wonder if here is a way to get rid of this "container" that after all is partly a parallel structure to "model"?
A typical workflow look like this:
create a diagram where results from different simulations below should be shown
model = load_fmu(fmu_model)
parDict['model.x_0'] = 1
parDict['model.a'] = 2
for key in parDict.keys(): model.set(key,parDict[key])
sim_res = model.simulate(10)
plot results...
model = load_fmu(fmu_model)
parDict['model.x_0'] = 3
for key in parDict.keys(): model.set(key,parDict[key])
sim_res = model.simulate(10)
plot results...
There is a function model.reset() that brings the state back to default values at compilation without loading again, but you need to do more than the following
model.reset()
parDict['model.x_0'] = 3
for key in parDict.keys(): model.set(key,parDict[key])
sim_res = model.simulate(10)
plot results...
So,  this does NOT work...
and after all parameters and initial values needs to be brought back and we still need parDict, but we may avoid the load-command though.

Only add existing variables in Matlab

I would like to add the sums of 5 one-column arrays in Matlab. The catch is that depending on previous inputs, any of these arrays may or may not exist, thus throwing an error when I try to add the sums of these arrays for post-processing.
After doing some digging I found the following function which I can use to return a logical statement if a certain variable exists in the workspace:
exist('my_variable','var') == 1
I'm not sure this helps me in this case though - Currently the line in which I add the sums of the various arrays looks as follows:
tot_deviation = sum(var1) + sum(var2) + sum(var3) + sum(var4) + sum(var4);
Is there a short way to add only the sums of the existing arrays without excessive loops?
Any help would be appreciated!
You can use if statements:
if ~exist('var1','var'), var1 = 0;end
if ~exist('var2','var'), var2 = 0;end
if ~exist('var3','var'), var3 = 0;end
if ~exist('var4','var'), var4 = 0;end
tot_deviation = sum(var1) + sum(var2) + sum(var3) + sum(var4) + sum(var4);
To my knowledge there is no quick way to do this in matlab. It seems to me that, depending on the structure of your code, you have the following alternatives:
1- Initialize all your variables to column arrays of zeros with something like
var = zeros(nbLines, 1);
2- Put all your columns vectors side to side in a single array and the use tot_deviation = sum(sum(MyArray)); which will work no matter how many columns and lines there is in the array.
3- If you pass your variables to a function you can check the number of inputs arguments inside the function using 'nargin' and then only proceed to sum the right number of variables.
I would recommend using the second method for it seem to me that it is the one that allows you to take the most advantage of matlab's array system which good.
The most robust solution is to initialise all of your variables to 0 at the top of the function. Then there is no chance they don't exist, and they influence the summation correctly.
Alternatively...
You could (read: shouldn't) use a really nasty eval trick here for flexibility...
vars = {'var1','var2','var3','var4'};
tot = 0;
for ii = 1:numel(vars)
if exist(vars{ii}, 'var')
tot = tot + eval(var);
end
end
I say it's "nasty" because eval should be avoided (read the linked blog). The check on the variable name existence mitigates some of the strife, but it's still not ideal.
As suggested in the MathWorks blog on evading eval, a better option would be a struct with dynamic field names. You could use almost the same syntax as above, but replace the if statement with
if isfield( myStruct, vars{ii} )
tot = tot + myStruct.(vars{ii});
end
This will avoid dynamically named variables and keep your workspace clean!

Matlab - using a function mulitple times in the same workspace, to add values and fields to a structure

I have a structure such as:
specimen.trial1 = 1
I now want to add another trial to the specimen, so that
specimen.trial1 = 1
specimen.trial2 = 2
I can do this without a problem within the workspace and command window. But, if I'm using a function to calculate the numbers for each trial (with dynamic fields), the new field and value erases the previous one. Eg:
function [specimen] = dummy(trial,value)
specimen.(trial) = value
end
run the function:
[specimen] = dummy('trial1',1)
then run the function again with different inputs, but keeping the structure intact in the workspace
[specimen] = dummy('trial2',2)
Instead of getting a structure with 2 fields, I get just one with Trial2 being the only field. Does that make any sense? What would like is to use the outputs of a function to progressively add to a structure.
Thank you,
Chris
Yes it makes sense, because you're creating a new struct specimen within your function.
Solution: pass the the previous specimen to the function as well.
function [specimen] = dummy(specimen,trial,value)
specimen.(trial) = value
end
and call:
[specimen] = dummy(specimen,'trial1',1)
or alternativly leave out the assignment at all and use the following
function [output] = dummy(value)
output = value
end
and call:
[specimen.trail1] = dummy(1)
which really depends on what you actually want to do. Put passing a name to a function which uses this name to define a struct is a little pointless unless you "use" that name otherwise. Also if you want to have input-dependent dynamic names you'd also go with the first alternative

Retrieve headers from a financial time-series object

I have code that creates a portfolio in matlab by merging two time series. How do I retrieve a vector of Headers for the funds such that I get a vector with the fund names from 'Port'?
Fund1ts=fints(Fund1Dates,Fund1Data,'Fund1');
Fund2ts=fints(Fund2Dates,Fund2Data,'Fund2');
%CREATE PORTFOLIO
Port=merge(Fund1ts,Fund2ts,'DateSetMethod','Intersection');
If you look at Port in the Command Window they are present. However if you open Port from Workspace Window then only the data exists hence my problem in retrieving it.
Thank you.
As Hugh Nolan also suggested in a comment, this should get you the names you are after:
fnames = fieldnames(Port, 1)
From the documentation:
fnames = fieldnames(tsobj, srsnameonly) returns field names depending upon the setting of srsnameonly. If srsnameonly is 0, the function returns all field names, including the common fields: desc, freq, dates, and times. If srsnameonly is set to 1, fieldnames returns only the data series in fnames.
Hence the 1 in the code-snippet above. It will return only Fund1 and Fund2.
Edit
It appears that there are two functions called fieldnames in Matlab:
The 'standard' function fieldnames:
names = fieldnames(s)
names = fieldnames(obj)
names = fieldnames(obj,'-full')
The function fieldnames which is part of the Financial Toolbox:
fnames = fieldnames(tsobj)
fnames = fieldnames(tsobj, srsnameonly)
If called with one input argument, they both operate similarly. However, for future readers of this answer: The particular answer given above works only for the Financial Toolbox-version of the function.