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.
Related
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.
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;
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
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);
After applying a sliding-window operation like stdfilt(i, ones(5, 5)) to an image in MATLAB, I would like to set the border pixels, the pixels calculated using padding, to NaN to mark them as meaningless. In this example, I would set the outermost two rows and columns to NaN. Given an M * M window, how can I set this border that is (M - 1) / 2 pixels wide to a specific value?
Suppose, r is the matrix (result of stdfilt). Here is an example how to assign NaN to borders.
In general, you need to specify the correct index.
>> r = rand(4)
r =
0.8147 0.6324 0.9575 0.9572
0.9058 0.0975 0.9649 0.4854
0.1270 0.2785 0.1576 0.8003
0.9134 0.5469 0.9706 0.1419
>> r([1, end], :) = nan
r =
NaN NaN NaN NaN
0.9058 0.0975 0.9649 0.4854
0.1270 0.2785 0.1576 0.8003
NaN NaN NaN NaN
>> r(:, [1, end]) = nan
r =
NaN NaN NaN NaN
NaN 0.0975 0.9649 NaN
NaN 0.2785 0.1576 NaN
NaN NaN NaN NaN
update: in general, since image is a matrix, your question is "how to set certain matrix values?". The answer is: "using matrix's indexes". There are many ways to do it (for example, by building matrix of indexes, logical mask, or using rows/columns coordinates). The decision what method to use usually depends on the speed of the operation for this specific task. For example, if you need to replace zeros by NaN's, it's faster to use a logical mask: r(r == 0) = nan, and so on.
First find where are NaN's in your matrix. Assume your image Name is A.
a = isnan(A);
This will create matric a with 0 at locations that are numbers, and 1 at locations that are NaN. Then find the location of Nan elements as:
[x,y]=find(a==1);
Then replace them with value V as:
for i=1:length(x)
A(x(i),y(i)) = V;
end
This will do the job, but this seems like the sort of function which would be in the image processing toolbox.
mask = logical(ones(size(i)));
width = (m - 1) / 2;
mask(width + 1:size(i, 1) - width, width + 1:size(i, 2) - width) = 0;
i(mask) = NaN;