Performing concatenation within a matrix MATLAB [duplicate] - matlab

This question already has answers here:
How do you concatenate the rows of a matrix into a vector?
(2 answers)
Closed 7 years ago.
I have an m x n matrix, how do I convert it to a column matrix of dimension (m x n) x 1?
Is there any library function in MATLAB? If not, how can I write one to do this?
Thanks in advance!

You can simply use the colon operator to flatten a matrix into a column vector. You will want to first take the transpose because by default, flattening is column-major and your post is row-major.
M = rand(4,3);
M =
0.8147 0.6324 0.9575
0.9058 0.0975 0.9649
0.1270 0.2785 0.1576
0.9134 0.5469 0.9706
M = M.';
M =
0.8147 0.9058 0.1270 0.9134
0.6324 0.0975 0.2785 0.5469
0.9575 0.9649 0.1576 0.9706
M = M(:);
M =
0.8147
0.6324
0.9575
0.9058
0.0975
0.9649
0.1270
0.2785
0.1576
0.9134
0.5469
0.9706

Related

How to write output of MATLAB to a txt file?

I would like to write output of Matlab code's result into a .txt file.
My code is :
for i=1:1000;
M{i}=rand(1,4)';
end
So I try :
fid=fopen('M.txt','wt');
fprintf(fid,'%.8f\n',M{i});
fclose(fid)
The result is 1*1000 cell and every cell has 4*1 matrice. But the output file has 1*4000 matrices with this. How can I write column by column to a .txt file.
Thanks in advance.
screenshot from matlab
I want to write down all values of matrix like below side by side for 1000 matrices.
0.9572 0.9572 0.9572 0.9572 0.9572 0.9572 0.9572 0.9572 0.9572 0.9572
0.4854 0.4854 0.4854 0.4854 0.4854 0.4854 0.4854 0.4854 0.4854 0.4854
0.8003 0.8003 0.8003 0.8003 0.8003 0.8003 0.8003 0.8003 0.8003 0.8003
0.1419 0.1419 0.1419 0.1419 0.1419 0.1419 0.1419 0.1419 0.1419 0.1419
As you mentioned your MATLAB version is R2019a, you can use writematrix directly:
>> n = 4;
>> m = rand(1,n);
>> M = repmat(m.',1,1000);
>> writematrix(M,'M.txt','Delimiter','space')
Your format specifier *.8f\n says print each value on a new line. If you want to print the four values as four columns, use a format specifier like this:
fprintf(fid,'%.8f %.8f %.8f %.8f\n',M{i});
If you want to write just one column of the data at a time, specify which column like this:
fprintf(fid,'%.8f\n',M{i}(1));
Then you'll have to repeat or loop to do the other 3 columns.

fillmissing with only last 5 observations instead of all

I am using Matlab's fillmissing function to fill missing values.
If you have a matrix that looks as follows:
A = rand(10,2);
A(end-5:end,1) = NaN;
% this gives:
A =
0.8147 0.1576
0.9058 0.9706
0.1270 0.9572
0.9134 0.4854
NaN 0.8003
NaN 0.1419
NaN 0.4218
NaN 0.9157
NaN 0.7922
NaN 0.9595
And you apply the function fillmissing as follows:
Afilled = fillmissing(A, 'previous')
then the corresponding matrix will look as follows:
Afilled =
0.8147 0.1576
0.9058 0.9706
0.1270 0.9572
0.9134 0.4854
0.9134 0.8003
0.9134 0.1419
0.9134 0.4218
0.9134 0.9157
0.9134 0.7922
0.9134 0.9595
Now however, the function does not take into account how many observations were actually missing (in this case 6).
I am looking for a way to take the number of observations into account before taking the last value. For example, only fill the missing observations based on the last 5 observations:
Afilled2 =
i=1 0.8147 0.1576
i=2 0.9058 0.9706
i=3 0.1270 0.9572
i=4 0.9134 0.4854
i=5 % missing 1 0.9134 0.8003
i=6 % missing 2 0.9134 0.1419
i=7 % missing 3 0.9134 0.4218
i=8 % missing 4 0.9134 0.9157
i=9 % missing 5 0.9134 0.7922
i=10 NaN 0.9595
MATLAB's fillmissing function doesn't have this functionality. Here is some simple code to do what you would like to do (fill along dimension 1 using the 'previous' method):
% parameter: maximum number of observations to fill with a given value
max_fill_obs = 5;
% loop over columns
for col = 1 : size(A, 2)
% initialize a counter (the number of previously filled values) to 0
counter = 0;
% loop over rows within column col, starting from the second row
for row = 2 : size(A, 1)
% if the current element is known, reset the counter to 0
if ~isnan(A(row, col))
counter = 0;
% otherwise, if we haven't already filled in max_fill_obs values,
% fill in the value and increment the counter
elseif counter < max_fill_obs
A(row, col) = A(row - 1, col);
counter = counter + 1;
end
end
end
This works if there are multiple blocks of NaN values, filling in only the first max_fill_obs values within each block. For example, try running it on the matrix defined by
A = rand(20,2);
A(5:10,1) = NaN;
A(13:19,1) = NaN;
This is a vectorized version of the above code:
Afilled = fillmissing(A, 'previous');
Afilled(movsum(isnan(A), [max_fill_obs, 0]) > max_fill_obs) = NaN;

How can i delete rows with zeros from a matrix and rebuild the matrix? [duplicate]

This question already has answers here:
in matlab delete an entire row if the elements in certain columns equal zero
(3 answers)
Closed 5 years ago.
I have a large nxm matrix. Here is some code to set up an example matrix E for illustration:
E = [(0:9).',[rand(9,3); zeros(1,3)]]
>> E =
0 0.8147 0.9649 0.7922
1 0.9058 0.1576 0.9595
2 0.1270 0.9706 0.6557
3 0.9134 0.9572 0.0357
4 0.6324 0.4854 0.8491
5 0.0975 0.8003 0.9340
6 0.2785 0.1419 0.6787
7 0.5469 0.4218 0.7577
8 0.9575 0.9157 0.7431
9 0 0 0
My question is how can transform matrix E into
>> E =
0 0.8147 0.9649 0.7922
1 0.9058 0.1576 0.9595
2 0.1270 0.9706 0.6557
3 0.9134 0.9572 0.0357
4 0.6324 0.4854 0.8491
5 0.0975 0.8003 0.9340
6 0.2785 0.1419 0.6787
7 0.5469 0.4218 0.7577
8 0.9575 0.9157 0.7431
In order to write it to a txt file without the zeros.
Since the size of this matrix is not fixed, it could have multiple rows like 9 in the above example, or look like
>> E =
0 0.8147 0.9649 0.7922
1 0.9058 0.1576 0.9595
2 0.1270 0.9706 0.6557
3 0.9134 0.9572 0.0357
4 0.6324 0.4854 0.8491
5 0.0975 0.8003 0.9340
6 0.2785 0.1419 0.6787
7 0.5469 0.4218 0.7577
8 0.9575 0.9157 0.7431
0 0 0 0
0 0 0 0
Thank you.
Does this cover all cases? If an element in column 2 == 0, delete it.
E = E(E(:,2) ~= 0,:);
Or if all columns but the first one have to be zero:
E = E(all(E(:,2:end) ~= 0,2),:);

Looping through measurement data then create vectors in Matlab

I have already looked at previous posts but can't find a satisfactory solution to my case yet.
I am new to Matlab and have input/output device data which i have arranged into column vectors, now i need to loop equal sized windows through the whole datafile by creating same sized vectors at each instance. The data has 600 columns as example table below. Sorry it doesnt look the best as it won't allow me to edit it properly:
All vectors i2, i3, i4,...,i600 are built exactly the same way as i1.
Data type ____ Columns 1 … 600
Input
0.20 0.37 0.21 -0.04 …
-0.06 0.01 0.31 0.17 ...
Output
0.34 -0.08 0.59 -0.04 …
0.11 0.06 0.72 0.18 …
-0.27 0.09 0.59 0.03 …
Each vector would have 14 elements from the data. So i1=[0.20; -0.06; 0.37; 0.01; 0.21; 0.31; -0.04; 0.17;...], i2=[0.37; 0.01; 0.21; 0.31; -0.04; 0.17;...], i3=[0.21; 0.31; -0.04; 0.17;...],..to i600. It means essentially vector i1 will be built by input data values in columns 1-7 as listed, and i2 will contain columns 2-8, while i3 columns 3-9 and so forth. As you can see, hence am trying to create data by forming 'overlapping' 14x1 input vectors. The outputs ie o1, o2,..will also be formed in exactly the same way only that vectors will be 21x1 in size, how do i build these vectors from this data?
I am now stuck please help,
Thank you in advance :) Tee
% Make a 2x600 array with random entries.
Q = rand( 2, 600 );
% The offset for the beginning of each
% set we want to extract from the above
% array. We subtract 7 from 600 since we are
% pulling off 14 elements at a time and thus
% have to stop at the 7th-to-last column.
offsets = 2 * ( 0 : 600 - 7 );
% These are indices of the elements we want
% organized by column. All we have to do is
% offset the numbers 1 thorugh 14 by the
% amounts found above.
v = (1:14)';
inds = repmat( v, 1, length( offsets ) ) + repmat( offsets, length(v), 1 );
% Now we can pull off the overlapping submatrices we want.
C = Q(inds);
Here is some example output:
>> Q(:,1:10)
ans =
0.8147 0.1270 0.6324 0.2785 0.9575 0.1576 0.9572 0.8003 0.4218 0.7922
0.9058 0.9134 0.0975 0.5469 0.9649 0.9706 0.4854 0.1419 0.9157 0.9595
>> C(:,1:2)
ans =
0.8147 0.1270
0.9058 0.9134
0.1270 0.6324
0.9134 0.0975
0.6324 0.2785
0.0975 0.5469
0.2785 0.9575
0.5469 0.9649
0.9575 0.1576
0.9649 0.9706
0.1576 0.9572
0.9706 0.4854
0.9572 0.8003
0.4854 0.1419
You can see that first row of C is the first 7 columns of Q, while its second column are columns 2-8 of Q.

Use vertcat to concatenate columns of a matrix using array of indices

Let's say we have the following random matrix
a=rand(6,5)
a =
0.8147 0.2785 0.9572 0.7922 0.6787
0.9058 0.5469 0.4854 0.9595 0.7577
0.1270 0.9575 0.8003 0.6557 0.7431
0.9134 0.9649 0.1419 0.0357 0.3922
0.6324 0.1576 0.4218 0.8491 0.6555
0.0975 0.9706 0.9157 0.9340 0.1712
and we have done an SVD decomposition of this matrix.
[U E V]=svd(a);
If we want to concatenate the first, third and fifth columns, we can do that like this
z=vertcat(U(:,1),U(:,3),U(:,5));
The dimensions of z are
[m,n]=size(z)
m =
18
n =
1
But suppose that I want the following thing: I will declare an array with elements of these indices or
b=[1 3 5]
b =
1 3 5
and then
z1=vertcat(U(:,b));
but the dimensions are
[m1 n1]=size(z1)
m1 =
6
n1 =
3
Is it possible that in z1=vertcat(U(:,b)); I change something so that it directly gives me result I want?
When you look at:
a(:,1) = 0.8147
0.9058
0.1270
0.9134
0.6324
0.0975
You get a vertical vector. By doing vertcat you add the other vertical vectors vertically resulting in a 18x1vector.
You could use horzcat if you want the other columns added as columns. By using b which is a horizontal vector MATLAB is changing the output accordingly.
Because svd returns a matrix of the same dimension as the input, same goes for U.
EDIT
For getting a 18x1 vector as result use either:
z1=reshape(z1,18,1);
or use
z1=z1(:);
This should do the trick
z1 = U(:,b);
z1 = z1(:);
what you done is proper, but you have to use reshape function at the last step, like that:
z1 = reshape(Z1,1,18);