How to clear variables of a mat file? - matlab

I have a mat file, named save.mat, which has two variables. I want to clear the variables and add some other variables. How could I clear/add variables inside a mat file?
Best

You can do this two ways, either through the Matlab GUI or through a script.
To do this within Matlab itself, simply navigate to the .mat file's directory, run 'clear' within your command window (make sure to save your current workspace if you need that data!), the double-click the .mat file to load it. From here you can use the workspace to delete and add variables to your heart's content.
If you want to do this in a script, set up something like this:
clear
load('save'); % load the .mat file
clear foo bar % removes the variables 'foo' and 'bar'
baz = 3; % adds the variable 'baz'
save('save'); % save over the old .mat file

To add one o more variables to an existing .mat file, you can use the save function by specifying the option -append.
To remove one or more variables from an existing .mat file you can:
load the .mat file into a struct using the load function: each read variable will be stored in a field of the struct
remove from that struct the the field corresponding to the varaible you want to delete from the original mat file by using the rmfield function
save the struct using the save function by specifying the option -struct: this will allow save the fields of a structure as individual variables
This is an example of the implementation:
% Define some varaible to be saved
a=1
b=2
c=3
% Save the varaibles
save('add_del.mat','a','b','c')
% Define an additional variable
d=4
% Add the new varaible to the ".mat" file
save('add_del.mat','d','-append')
% Load the ".mat" file into a struct
str=load('add_del.mat')
% Delete the field corresponding to the varaible to delete
str=rmfield(str,'b')
% Save the fields of a structure as individual variables
save('add_del.mat','-struct','str')
Hope this helps.
Qapla'

#excaza has made a good recommendation, I think. To verify that the matfile command works as suggested, try the following:
filename = ('file.mat');
m = matfile(filename,'Writable',true);
y = 23;
m.y = y;
clear y
load(filename);
display(y);
y = 24;
m.y = y;
clear y
load(filename);
display(y);

Related

Performing operations on a variable number of workspace elements in MATLAB

new MATLAB user here so apologies if this seems like a silly question. I have the following list of variables (doubles) in my workspace:
E1_01Strain E1_06Strain E1_07Strain E1_08Strain E1_09Strain E1_10Strain
E1_01Stress E1_06Stress E1_07Stress E1_08Stress E1_09Stress E1_10Stress
These are lists of numbers. I would like to remove the last n elements from each variable. I can do it with the command
E1_01Strain = E1_01Strain(1:end-100)
but it's impractical because later I'm going to have to do it on many, many more similar variables. Therefore I wanted to write a function that accepts as inputs a list of the workspace variables (as in, I highlight the variables I want and drag and drop into the function input) and removes from each one n elements.
I understand that I can write a function like this:
function [X1, X2, X3, X4] = Remove_n_elements[n, X1, X2, X3, X4]
X1 = X1(1:end-100);
X2 = X2(1:end-100);
X3 = X3(1:end-100);
X4= X4(1:end-100);
end
but that would mean that I would have to change the number of inputs, outputs, and the lines of code in the function every time. I'm sure there's a better way to do it but I can't figure it out.
I keep thinking that there might be a way to do it by looping over all the inputs but I can't get it to work since (as far as I know) I need to create a list of the inputs and then the operation is performed only on the elements of that list, not the inputs themselves.
I was looking at Passing A Variable Number of Arguments into a Function and from that using inputParser from https://www.mathworks.com/help/matlab/matlab_prog/parse-function-inputs.html but since I'm new to MATLAB I'm not sure how to use it for my case.
I used the code provided by il_raffa for a bit but followed his advice and went back and reconsidered how the script functions. After some more digging I wrote the following script that does exactly what I need. This script extracts the columns des_cols from all .csv files in a folder and plots them together. It then makes another plot of the averages.
files = dir('*.csv'); % navigate to the folder that you want to run the script on in MATLAB
avgStress = [];
avgStrain = [];
set(groot, 'DefaultLegendInterpreter', 'none') % the names of my .csv files have underscores that I want to see in the legend, if you don't want this then comment this line
hold on; %comment this and hold off further down if you want separate plots for every .csv
for file = files'
csv = xlsread(file.name);
[n,s,r] = xlsread(file.name);
des_cols = {'Stress','Ext.1(Strain)'}; % type here the names of the columns you want to extract
colhdrs = s(2,:);
[~,ia] = intersect(colhdrs, des_cols);
colnrs = flipud(ia);
file.name = n(:, colnrs);
file.name = file.name(1:end-600,:); % I wanted to remove the last 600 rows but if you want them all, remove the -600
plot(file.name(:,2),file.name(:,1),'DisplayName',s{1,1});
avgStress = [avgStress file.name(1:1500,1)]; % calculates the average stress for the first 1500 points, you can change it to whatever you want
avgStrain = [avgStrain file.name(1:1500,2)];
end
ylabel({'Stress (MPa)'}); % y-axis label
xlabel({'Strain (%)'}); %x-axis label
title({'E_2'}); % title of the plot
legend('show');
hold off; % commment this if you want different plots for all .csv files
avgStress = mean(avgStress,2);
avgStrain = mean(avgStrain,2);
plot(avgStrain,avgStress);
This creates two plots, one with all the raw data and another with just the averages. I hope this helps anyone that might have a similar issue.
The best thing you can do is to review the architecture of your SW in order to avoid the needs to perform such operations on the Workspace variables.
That is: how those variables are created? Are these variables loaded from a ".mat" file? etc.
Anyway, in order to avoid using the eval function and given your situation, a possible approach could be:
identify the names of the varailbes by using the function who. You can specify in the call to who the root name of the varaibles and use the * as, for example, who('E1*'). Make sure it fit wiht the desired variables. You can also use regexp to better refine the selection of the variables
save these varaibles in a temporary .mat file: the name (including the path of the temporary file can be created with the function tempname
load the temporary .mat file: this will create a struct in the Workspace whose fields are the variables you want to midify
call the function to remove the undesired elements form the fields of the struct. The function have to return the updated struct
save the updated struct in the temporary file
load again the temporary file by specifying the option -struct which allows loading the content of the file as single varaibles
The function to remove the undesired elements can be made as follows:
get the nams of the struct's fields by using the function fieldnames
loop over the filed of the struct by using the dynamic field names property
remove the undesired elements form the fields
return the updated struct
A possible implementatin could be:
Code "before" the call to the function
% Get the names of the variables
list_var=who('E1*')
% Define the name of a temporary ".mat" file
tmp_file=tempname
% Save the variables in the temporary ".mat" file
save(tmp_file,list_var{:});
% Load the variables in a struct
sel_vars=load(tmp_file);
% Call the function to remove the elements
out_str=Remove_n_elements(8,sel_vars)
Function to remove the undesired elements
function sel_vars=Remove_n_elements(n,sel_vars)
% Get the names of the fields of the struct
var_names=fieldnames(sel_vars)
% Loop over the fields and remove the undesired elements
for i=1:length(var_names)
sel_vars.(var_names{i})=sel_vars.(var_names{i})(1:end-n)
end
Code "after" the call to the function
% Save the updated struct in the temporary ".mat" file
save(tmp_file,'-struct','out_str')
% Load the updated struct as separate variables
load(tmp_file)

Sequence of data in MATLAB

I have sequence of data in MATLAB: data1, data2, data3,.... I want to print them one after one. I am stuck on that.
clear; clc;
data1=[1,2];
data2=[3,4];
n=[1,2];
for i=1:length(n)
fname(i,:)=sprintf('data%d',n(i));
end
Does this work for you?
clear; clc;
data1=[1,2];
data2=[3,4];
n=[1,2];
for i=1:length(n)
eval(['data' num2str(n(i))])
end
A possible solution not involving the use of eval could be the following.
Basically it consists of the following steps:
Get the list of data in the Workspace (with who function)
Identify the data to be printed (using regexp to identfy the variables names of the form dataxwhere x is a number)
save these variables in a temporary .mat file
load the .mat file in a struct which allows to have only the variables to be printed
exploit the dynamic field names to get access to the variables
This the code:
% Define some data
data1=[1,2];
data2=[3,4];
data3=rand(5)
data4a=rand(5)
dataaaa3=rand(5)
var_1=1
b=2
% Get the list of data in the Workspace
str=who
% Identify the data to be printed
var_to_print=regexp(str,'data\d$')
idx=~cellfun(#isempty,var_to_print)
% Down select the variables to be printed
str{idx}
% Generate a temporary ".mat" filename
tmp_name=[tempname '.mat']
% Save the data to be printed in the temporary ".mat" file
save(tmp_name,str{idx})
% Load the data to be printed into a struct
v=load(tmp_name)
% Get the names of the varaibles to be printed
f_name=fieldnames(v)
% print the value of the variables
for i=1:length(f_name)
[char(f_name(i)) ' = ']
v.(f_name{i})
end
% Move the temporary ".mat" file in the recycle folder
recycle('on')
delete(tmp_name)
Hope this helps.
Qapla'

Accessing variables from different files in matlab

I have a "data.m" file that contains a handful of large arrays that I do not want in my main file. For all intents and purposes, they are in the form
a1 = [1,2,3]
a2 = [3,4,5]
How can I access a1 and a2 from another script? Or should I be putting these in a .mat file? If so, how do I do that?
Heres an easy way:
Inside data.m, output your arrays:
function [a1, a2] = data( )
...
end
You can access these arrays from your "main" function (e.g thefunc.m) like this:
function [ ] = thefunc( )
//say you want to store array a1 into a variable X, and array a2 into variable Y
[X, ~] = data;
[~, Y] = data;
end
Of course, thefunc.m and data.m should be in the same working directory.
If the values of the variables are constant, it would be better to store these in MAT files. Also, try to use functions instead of scripts unless it is necessary to use scripts. Scripts define global variables which could lead to inadvertently overwriting variables among many other issues.
Say we have data.m of Yours and a function foo.m that is about to use variables from there.
Turn the data.m into this form:
function[]=data() % defines a function with no output nor input
a1=[1 2 3];
b2='string';
%Your definitions and other code
save('DataFile.mat'); % save EVERY varible used in the code with it's name
Then in foo.m
function[]=foo()
load('DataFile.mat'); % Load all variables saved in DataFile.mat
disp(b2);
You can also prevent temporary variables to be saved with the mandatory ones by deleting them just before save command by clear temp1 temp2
If you want to save some variables, say a1 in one file and other in different file You can use save('DataFile.mat','a1')
If you want to load specific variables You can use load('DataFile.mat','b1')

Load .mat file from inside function

In Matlab, I have a little function init() placed inside "init.m" that I use to load all the data I need when I start up matlab. Files loaded include .mat files and a .png file. To load the .png file, another function is called, importfile(filename). When I place the two functions in seperated files, everything works great. However, when I place this second function inside the file "init.m", and I call init() from the command line, only the png appears in my workspace variables. I know that the first function in a .m file is the main function and additional functions are considered local functions.
Can anyone explain this behavior? I am used to C++ and it would be helpful to precisely understand how Matlab handles paths, workspaces and multiple functions inside files.
Here are the relevant functions:
function init()
cd('~/thesis/data/');
files = dir('*.mat');
for i=1:length(files)
disp(files(i).name);
load(files(i).name);
end
importfile('./K2.png');
end
function importfile(fileToRead1)
%IMPORTFILE(FILETOREAD1)
% Imports data from the specified file
% FILETOREAD1: file to read
% Auto-generated by MATLAB on 06-Jan-2015 12:10:28
% Import the file
rawData1 = importdata(fileToRead1);
% For some simple files (such as a CSV or JPEG files), IMPORTDATA might
% return a simple array. If so, generate a structure so that the output
% matches that from the Import Wizard.
[~,name] = fileparts(fileToRead1);
newData1.(genvarname(name)) = rawData1; %#ok<DEPGENAM>
% Create new variables in the base workspace from those fields.
vars = fieldnames(newData1);
for i = 1:length(vars)
assignin('base', vars{i}, newData1.(vars{i}));
end
end
load() only loads data into your function workspace. When you had init() on its own I'm assuming you had it as a script and not as a function.
e.g.
% Script
cd('~/thesis/data/');
files = dir('*.mat');
for i=1:length(files)
disp(files(i).name);
load(files(i).name);
end
importfile('./K2.png');
vs.
function init()
% Function
cd('~/thesis/data/');
files = dir('*.mat');
for i=1:length(files)
disp(files(i).name);
load(files(i).name);
end
importfile('./K2.png');
end
A script's workspace is the base MATLAB workspace, so it's functioning as intended. When changed to a function it loads your data into the function workspace and discards it when the funciton completes execution. The reason the image still loads correctly is because you're explicitly assigning it to the base workspace.
To get around this, you could change init() to:
function init()
% Function
cd('~/thesis/data/');
files = dir('*.mat');
for i=1:length(files)
disp(files(i).name);
evalin('base', strcat('load(''', files(ii).name, ''')'));
end
importfile('./K2.png');
end
And keep importfile as a local function, which produces what I believe you're expecting. I'm not a huge fan of the syntax and blindly assigning workspace variables but it achieves the goal.
My apologies, the answer is contained in the (MATLAB autogenerated) code:
% Create new variables in the base workspace from those fields.
vars = fieldnames(newData1);
for i = 1:length(vars)
assignin('base', vars{i}, newData1.(vars{i}));
end
The code also failed if I place it inside a seperate function; only not placing it in a function at all worked, as matlab considers this environment local.

How to delete only variables created by a specific matlab script

Is there some way to delete only the variables generated in a matlab script at the end of the script and not any other variables of the workspace which are not generated in the script?
Note : The script is not a function.
Basically I want to do the following in one line
save abc.mat % saves the whole workspace
some_script % call the script
clear % deletes the variables created by the script along with the whole workspace
load abc.mat % again loads the whole earlier workspace
Use who before the script, then after the script; compare the results (setdiff) to detect variables created in the script, and then clear only those.
Variable names varsbefore, varsafter and varsnew in the following code should be guaranteed not to be used before the script or within the script.
varsbefore = who; %// get names of current variables (note 1)
some_script
varsafter = []; %// initiallize so that this variable is seen by next 'who'
varsnew = []; %// initiallize too.
varsafter = who; %// get names of all variables in 'varsbefore' plus variables
%// defined in the script, plus 'varsbefore', 'varsafter' and 'varsnew'
varsnew = setdiff(varsafter, varsbefore); %// variables defined in the script
%// plus 'varsbefore', 'varsafter' and 'varsnew'
clear(varsnew{:}) %// (note 2)
Notes about the code:
who used with an output argument returns a cell array of strings containing the names of all variables.
The functional form of clear is used, with input arguments in the form of a comma-separated list generated from a cell array.
You can create structures of variables in this way:
FOO_STRUCT.foo_var = var_from_abc.mat + rand(1);
FOO_STRUCT.foo_var2 = 10*log10(FOO_STRUCT.foo_var);
FOO_STRUCT.foo_var3 = FOO_STRUCT.foo_var2 + var_from_abc.mat;
The upper case part is the structure name. The lower case part is the variable.
You can use variables from the workspace in your script, make your work and at the end of the script you delete the entire structure
clear FOO_STRUCT