Load values from a text file in MATLAB - matlab

I would like to load variables from a text file.
For example, my text file, varA, varB, and varC.
In MATLAB, I would like to give these variables values so that every variable is a 2x2 matrix.
So from the text file containing the above information I would get a matrix that looks like this:
[ 1 2 3 4 5 6;
1 2 3 4 5 6]
Is this possible?
I added a second example to try to make things a little clearer.
My text file, text.txt, looks like this
x1 x2 x3
In MATLAB my .m file gives the values to these variables like
x1 = [1 1; 1 1]
x2 = [2 2; 2 2]
x3 = [3 3; 3 3]
So, when I import my textfile I would get
a = (textfile)
a = [1 1 2 2 3 3 ; 1 1 2 2 3 3]
I basically try to adapt a genetic algorithm (GA) on a very huge problem (of travelling salesman problem (TSP) type). The problem is that every variable I have is a matrix and the crossover, fitness and mutation codes get pretty complicated. And I am having problems of making a random start population as well.
I would like to randomly select, let's say 30 variables, from a list with 256 so that the variable can only be picked once. Each variable however have their own specific values in a 2*2 matrix that cannot be changed.
I would like to use randperm and then put an x before every value making them variables instead of values...

If the data in the text file looks like this (strings separated by spaces):
x1 x2 x3 ...
You can read the strings into a cell array using TEXTSCAN like so:
fid = fopen('file.txt','r');
A = textscan(fid,'%s');
fclose(fid);
A = A{:};
A now stores the strings in a cell array: {'x1'; 'x2'; 'x3'; ...}. Now, to make a variable out of one of these strings and assign it a value, I would use ASSIGNIN:
assignin('base',A{1},[1 2; 1 2]);
This will create a variable x1 in the base workspace and assign it the value [1 2; 1 2]. The first argument can be either 'base' or 'caller' to create a variable in either the MATLAB base workspace or the workspace of the caller function. You would repeat this for each string name in A, giving it whatever value you want.
ALTERNATE OPTION:
This is an alternate answer to the one I gave you above. The above answer addresses the specific problem you raised in your question. This answer gives you a whole other option to potentially avoid doing things the way you were describing them in your question, and it will hopefully make things easier for you...
If I understand your problem, you basically have 256 2-by-2 matrices, and you want to randomly pick 30 of them. Each of these 2-by-2 matrices sounds like it is stored in its own variable (x1 to x256). Instead, I would suggest storing all 256 matrices in just one variable as either a 3-D array:
xArray = zeros(2,2,256); % Initialize all matrices as [0 0; 0 0]
xArray(:,:,1) = [1 1; 2 2]; % This enters a value for the first matrix
or a cell array:
xArray = cell(1,256); % Initializes an empty array of cells
xArray{1} = [1 1; 2 2]; % Enters a value for the first matrix
You would have to initialize all the values first. Then if you want to randomly pick 30 values, you can next randomize the order of either the third dimension of the 3-D array or the order of the cell array by using RANDPERM:
startOrder = 1:256; % The default order of the matrices
index = randperm(256); % Randomly order the numbers 1 to 256
xArray = xArray(:,:,index); % For a 3-d array
xArray = xArray(index); % For a cell array
Then just use the first 30 entries in xArray for your calculations (instead of the individual variables like you were before):
x = xArray(:,:,1); % Puts the first matrix from the 3-D array in x
x = xArray{1}; % Puts the first matrix from the cell array in x
You can keep repeating the use of RANDPERM to keep generating new randomized arrays of matrices. If you have to keep track of which original matrices you are using, you have to add this line after you randomize xArray:
startOrder = startOrder(index);
Now the entries of startOrder will tell you the original position a matrix was in. For example, if the first array entry in startOrder is 40, then the matrix in the first position of xArray was originally the 40th matrix you entered when you initialized xArray.
Hope this helps!

Related

Extracting a matrix from a cell vector in MATLAB

A sparse matrix is a large matrix with almost all elements of the same
value (typically zero). The normal representation of a sparse matrix
takes up lots of memory when the useful information can be captured
with much less. A possible way to represent a sparse matrix is with a
cell vector whose first element is a 2-element vector representing the
size of the sparse matrix. The second element is a scalar specifying
the default value of the sparse matrix. Each successive element of the
cell vector is a 3-element vector representing one element of the
sparse matrix that has a value other than the default. The three
elements are the row index, the column index and the actual value.
Write a function called "sparse2matrix" that takes a single input of a
cell vector as defined above and returns the output argument called
"matrix", the matrix in its traditional form. Consider the following
run:
cellvec = {[2 3], 0, [1 2 3], [2 2 -3]};
matrix = sparse2matrix(cellvec)
matrix =
0 3 0
0 -3 0
Good morning/afternoon/night, everyone
I was wondering if you could help me with this.
I am trying to complete this, but I am not sure how to deal with this. I understand that I am interested in the first part of the cell vector, but I am not sure about how to tell Matlab I need that. This is my code:
function matrix = sparse2matrix(x)
A = [2 3];
B = 0;
C = [1, 2, 3];
x = {A, 0, C};
matrix = cell2mat(x);
end
The result of this code is different from the result I showed above.
I am not getting the right answer and honestly I do not know what to do, so I would appreciate if you guide me a little bit.
Not the most elegant way of doing it but it gets the job done. Uses the cell2mat() function and indexing to grab the necessary values for each step. A for-loop is then used to obtain the 3-element vectors that is used to change the array values from the default values in the respective indices.
cellvec = {[2 3], 0, [1 2 3], [2 2 -3]};
[matrix] = sparse2matrix(cellvec)
function [matrix] = sparse2matrix(x)
Matrix_Size = cell2mat(x(1,1));
Matrix_Height = Matrix_Size(1);
Matrix_Width = Matrix_Size(2);
Default_Value = cell2mat(x(1,2));
matrix = Default_Value*ones(Matrix_Height,Matrix_Width);
Triplets = x(3:end);
Number_Of_Triplets = length(Triplets);
for Triplet_Index = 1: Number_Of_Triplets
Current_Triplet = cell2mat(Triplets(1,Triplet_Index));
Row = Current_Triplet(1,1);
Column = Current_Triplet(1,2);
Value = Current_Triplet(1,3);
matrix(Row,Column) = Value;
end
end
Explanation:
The first line in the local function sparse2matrix() indicates to retrieve row 1, column 1 of the cell array x and then convert it to a matrix. The conversion is done using the cell2mat() function.
Matrix_Size = cell2mat(x(1,1));
Results in:
Matrix_Size = [2 3]
The following line indicates to grab index 1 of the previous array Matrix_Size. This will be used to determine the height of the output array matrix. This is done in a similar fashion to evaluate the Matrix_Width using index 2.
Matrix_Height = Matrix_Size(1);
Results in:
Matrix_Height = 2
Ran using MATLAB R2019b

MATLAB: Adding vectors to a matrix and counting the number of non zeros

I have the following problem:
A = [] % matrix
Q = [] % number on non zero in each row
for i=1:10
% I generate a path with name path
% add the path to the matrix A
end
% count number on non zero numbers in each row
How can I do that?
Here is an illustrative example:
If the path in first iteration was: path = [ 1 2 3 4 ]
In the second iteration: path = [ 4 5 6 ]
In third iteration: path = [ 7 2 ]
Then A should be like this:
A =
[1 2 3 4 ,
4 5 6 0 ,
7 2 0 0 ]
After, I would like a vector to show me the number of numbers different than zero in each row like so:
Q = [4 3 2]
Given your comments, this is what I would suggest that you do:
Because the actual paths are not known a priori, I would suggest that you store all of the paths in a cell array. Given your for loop condition, I'm assuming that there will be 10 paths. The actual paths we don't know, but we know there will be 10.
Write some code that will figure out the maximum length of path as this will dictate the size of our matrix A.
Create the matrix A then store of all the paths in, with zeroes appended at the end of each path should they not be the size of the maximum length of the path.
Using the matrix A, figure out how many non-zeroes there are.
Without any further ado, here is the code you are seeking. With each step, I will explain what I am doing to get the desired step.
Step #1
pathCellArray = cell(10, 1);
for i = 1 : 10
%// Insert path generation code here...
%// Assume that the variable is called
%// 'path' that stores this path
%//..
pathCellArray{i} = path;
end
This should be self-explanatory. For each path that you generate, store it in its corresponding cell. The reason why we are placing each path in a cell is because the length of each path is variable. We are also doing this so we can figure out how many columns we need to allocate for A. Also take note that I am creating a cell array of columns. The reason why is because when we do a reconstruction and solve for A, it will make things easier.
Step #2
%// Use cellfun that takes in a cell array and we will
%// generate an array as output that contains the
%// size of each path. We will find the maximum of
%// all of these that will dictate our size of A
lengthArray = cellfun(#length, pathCellArray);
numCols = max(lengthArray);
Now this is something cool. You probably have never seen cellfun before. How cellfun works is that we specify a custom function, and cellfun will apply this function to every element to this cell. For the output of cellfun the i'th position of the output is the output of the custom function for each i'th position of the input cell array. As such, what we are doing here is that we are generating a length array (stored as lengthArray) that goes through each cell and figures out how big the path is. lengthArray will thus store how long each path is. Once we do that, we figure out what the longest path is so we know how big A will be.
Step #3
pathCellArrayAppend = cellfun(#(x) [x zeros(1,numCols-length(x))], ...
pathCellArray, 'UniformOutput', false);
A = cell2mat(pathCellArrayAppend);
This code is probably the most complex out of all that you have dealt with. What I am basically doing here is taking that cell array of paths that I created, and generating a new cell array where each element in the cell (which is our path) gets appended with zeroes up until the length of the longest path. If you look, the custom function we have generated basically creates the array that first stores the path that we want, then zero-pads the rest of the array with zeroes. We have to specify UniformOutput to false as because the output of the the custom function is no longer a single value. It is an array as the output, which is why this flag is set to false. The output of this call to cellfun will generate 10 cell arrays where each element is a path and is zero-padded with zeroes. We then call cell2mat to convert this cell array back to matrix form, and A is your result.
Step #4
Q = cellfun(#(x) sum(x ~= 0), pathCellArrayAppend);
We thus call cellfun again. This time we take a look at our cell array that has all of the paths that are zero-padded. We go through each cell, and count how many non-zero entries there are. Q will store this result. Note that we don't need to set UniformOutput to false as the output of the custom function is a single number.
Using your example that you have provided, here is how the code will look with their corresponding outputs:
%// Step #1 - Simulated
p1 = [1 2 3 4];
p2 = [4 5 6];
p3 = [7 2];
pathCellArray = {p1; p2; p3};
%// Step #2
lengthArray = cellfun(#length, pathCellArray)
>> lengthArray =
4
3
2
numCols = max(lengthArray)
>> numCols =
4
%// Step #3
pathCellArrayAppend = cellfun(#(x) [x zeros(1,numCols-length(x))], ...
pathCellArray, 'UniformOutput', false);
A = cell2mat(pathCellArrayAppend)
>> A =
1 2 3 4
4 5 6 0
7 2 0 0
%// Step #4
Q = cellfun(#(x) sum(x ~= 0), pathCellArrayAppend)
>> Q =
4
3
2
NB: You could simply use Step #2 as your Q, provided that your paths are non-zero. If there are, then you need to go right to Step #4.

frequency of each vector value in another vector matlab

I need to calculate the frequency of each value in another vector in MATLAB.
I can use something like
for i=1:length(pdata)
gt(i)=length(find(pf_test(:,1)==pdata(i,1)));
end
But I prefer not to use loop because my dataset is quite large. Is there anything like histc (which is used to find the frequency of values in one vector) to find the frequency of one vector value in another vector?
If your values are only integers, you could do the following:
range = min(pf_test):max(pf_test);
count = histc(pf_test,range);
gt = count(ismember(range,a));
gt(~ismember(unique(a),b)) = 0;
If you can't guarantee that the values are integers, it's a bit more complicated. One possible method of it would be the following:
%restrict yourself to values that appear in the second vector
filter = ismember(pf_test,pdata);
% sort your first vector (ignore this if it is already sorted)
spf_test = sort(pf_test);
% Find the first and last occurrence of each element
[~,last] = unique(spf_test(filter));
[~,first] = unique(spf_test(filter),'first');
% Initialise gt
gt = zeros(length(pf_test));
% Fill gt
gt(filter) = (last-first)+1;
EDIT: Note that I may have got the vectors the wrong way around - if this doesn't work as expected, switch pf_test and pdata. It wasn't immediately clear to me which was which.
You mention histc. Why are you not using it (in its version with two input parameters)?
>> pdata = [1 1 3 2 3 1 4 4 5];
>> pf_test = 1:6;
>> histc(pdata,pf_test)
ans =
3 1 2 2 1 0

Vectorizing the Notion of Colon (:) - values between two vectors in MATLAB

I have two vectors, idx1 and idx2, and I want to obtain the values between them. If idx1 and idx2 were numbers and not vectors, I could do that the following way:
idx1=1;
idx2=5;
values=idx1:idx2
% Result
% values =
%
% 1 2 3 4 5
But in my case, idx1 and idx2 are vectors of variable length. For example, for length=2:
idx1=[5,9];
idx2=[9 11];
Can I use the colon operator to directly obtain the values in between? This is, something similar to the following:
values = [5 6 7 8 9 9 10 11]
I know I can do idx1(1):idx2(1) and idx1(2):idx2(2), this is, extract the values for each column separately, so if there is no other solution, I can do this with a for-loop, but maybe Matlab can do this more easily.
Your sample output is not legal. A matrix cannot have rows of different length. What you can do is create a cell array using arrayfun:
values = arrayfun(#colon, idx1, idx2, 'Uniform', false)
To convert the resulting cell array into a vector, you can use cell2mat:
values = cell2mat(values);
Alternatively, if all vectors in the resulting cell array have the same length, you can construct an output matrix as follows:
values = vertcat(values{:});
Try taking the union of the sets. Given the values of idx1 and idx2 you supplied, run
values = union(idx1(1):idx1(2), idx2(1):idx2(2));
Which will yield a vector with the values [5 6 7 8 9 10 11], as desired.
I couldn't get #Eitan's solution to work, apparently you need to specify parameters to colon. The small modification that follows got it working on my R2010b version:
step = 1;
idx1 = [5, 9];
idx2 = [9, 11];
values = arrayfun(#(x,y)colon(x, step, y), idx1, idx2, 'UniformOutput', false);
values=vertcat(cell2mat(values));
Note that step = 1 is actually the default value in colon, and Uniform can be used in place of UniformOutput, but I've included these for the sake of completeness.
There is a great blog post by Loren called Vectorizing the Notion of Colon (:). It includes an answer that is about 5 times faster (for large arrays) than using arrayfun or a for-loop and is similar to run-length-decoding:
The idea is to expand the colon sequences out. I know the lengths of
each sequence so I know the starting points in the output array. Fill
the values after the start values with 1s. Then I figure out how much
to jump from the end of one sequence to the beginning of the next one.
If there are repeated start values, the jumps might be negative. Once
this array is filled, the output is simply the cumulative sum or
cumsum of the sequence.
function x = coloncatrld(start, stop)
% COLONCAT Concatenate colon expressions
% X = COLONCAT(START,STOP) returns a vector containing the values
% [START(1):STOP(1) START(2):STOP(2) START(END):STOP(END)].
% Based on Peter Acklam's code for run length decoding.
len = stop - start + 1;
% keep only sequences whose length is positive
pos = len > 0;
start = start(pos);
stop = stop(pos);
len = len(pos);
if isempty(len)
x = [];
return;
end
% expand out the colon expressions
endlocs = cumsum(len);
incr = ones(1, endlocs(end));
jumps = start(2:end) - stop(1:end-1);
incr(endlocs(1:end-1)+1) = jumps;
incr(1) = start(1);
x = cumsum(incr);

Combination of colon-operations in MATLAB

I have a question concerning the colon operator and expansion of vectors in MATLAB. My problem is to understand how the following line of code expands, to be able to use it for other sequences. The line of MATLAB code is:
a(1:2:5) = 1:-4:-7
Note that a is not defined before the expansion. This returns the vector
a = 1 0 3 0 -7
I know how the colon operator works with {start}:{step}:{stop}, my problem is to understand how and why the combination of a(1:2:5)and 1:-4:-7 returns a vector of five elements with zeros in position 2 and 5?
Whenever Matlab detects you're indecing to an element outside the current bounds of the matrix/array, it will automatically pad the missing elements with zeros:
>> clear b; b(10) = 5
b =
0 0 0 0 0 0 0 0 0 5
This feature is both very useful, and very dangerous. It is useful for the fact declarations can be made very easy, such as your own case. You can create a whole array of custom-made classes by issuing something like
myClassArray(500) = myClass(1, 2);
which is infinitely better than something like
% cannot pre-allocate (zeros() or ones() give double/uint8/..., not myClass)
for ii = 1:499
myClassArray(ii) = myClass; % so, growing array
end
myClassArray(500) = myClass(1,2);
But, growing arrays can be hard to spot:
a = zeros(10,1);
for ii = 1:10
a(ii+1) = rand;
end
which can make performance drop tremendously. Also, when you translate code prototyped in Matlab to a statically-typed language like C++, copying this code will result in buffer overflows and thus segfaults.
Now, going back to your case:
clear a; a(1:2:5) = 1:-4:-7
The 1:2:5 will expand to the array [1 3 5], and the 1:-4:-7 will give the values [1 -3 -7]. Since the variable a does not exist yet, Matlab will create a new one and fill the elements [1 3 5] with the values [1 -3 -7]. The indices that have been skipped in order to initialize variable a (namely, [2 4]) will then have been initialized automatically to zero.
If you're familiar with Python, it's a bit like the syntax to assign multiple values to multiple variables
x,y = 1,2
But in your Matlab case, these different variables are indices to a non-existent array, which requires "filling the holes with something" to make it a valid, consistent array.
Does this make things clear?
when you define a(1:2:5), it creates a size 5 vector (zero-valued), and selecting odd indexed(3 of them exists) cells. 1:-4:-7 creates three values (not five). Finally your selected three cells are filled with data of 3 values coming from 1:-4:-7