I am trying to exercise myself in Matlab. I am trying to select randomly two lines from a file named data.dat.
My data.dat file looks like this:
12 4 6.1 7
14 4 8.4 62
7 56.1 75 98
9.7 54 12 35
2 4 8 7.8
To select 2 lines randomly from the data.dat here is how I am proceeding:
close all;
clear all;
%----------------------%
% Choose random lines
%----------------------%
M = load('data.dat');
N=2; %number_of_lines
file_number = 2; %save each two lines in new file: selection_1, selection_2
Now I am saving the two selected lines in new files sequentially.
for k = 1:file_number
i = randi(length(M),N);
B=M(i,:)
filename=['samples_',int2str(k),'_mc.dat']
save (filename, 'B', '-ascii')
clear B;
end
I don't know why but I have more than 2 lines in each new files. Could you please explain me where did I made a mistake.
I think you are making a mistaking when you generate the random numbers, as indicated by GameOfThrows.
i = randi(length(M),N); % gives you a matrix NxN of numbers
i = randi(length(M),[N,1]); % gives you a column of N numbers
Related
I need to save a 3D matrix in a text file that will be loaded in Matlab (which I don't master). My first idea was to do it with a .csv like this, (consider a 3x3x3 matrix):
row 1: v[0][0][0],v[0][0][1] ,v[0][0][2]
row 2: v[0][1][0],v[0][1][1] ,v[0][1][2]
row 3: v[0][2][0],v[0][2][1] ,v[0][2][2]
row4: v[1][0][0],v[1][0][1] ,v[1][0][2]
...
Like this, I must inform the user separately about the number of x an y dimensions. Not too clean, but not a big drama.
My question is, how could I load and plot in Matlab a dataset like this? Values are 1/0.
Is there any smarter way of doing this. I am exporting from Java.
Thanks!
I can't think of a way that you can omit storing the dimensions of the matrix (at least two of them should be mentioned). But when it comes to storing values in a file, I suggest that you do not bother to even write them in tabular format. All you need to know about MATLAB is the order of elements in a matrix. Take a look at this example:
%% create a 3d matrix
% a = 1+randi(5);
% b = 1+randi(5);
% c = 1+randi(5);
a = 2; b = 3; c = 4;
M = reshape(1:a*b*c, a, b, c)
This is how the matrix looks like:
M(:,:,1) =
1 3 5
2 4 6
M(:,:,2) =
7 9 11
8 10 12
M(:,:,3) =
13 15 17
14 16 18
M(:,:,4) =
19 21 23
20 22 24
Now let's write it in a text file:
%% writing matrix in the text file,
% translate it to your target language
fid = fopen('matrix.txt', 'w');
fprintf(fid, '%d,%d,%d\n', a, b, c);
for k=1:c
for j=1:b
for i=1:a
fprintf(fid, '%-.8g\n', M(i, j, k));
end
end
end
fclose(fid);
This is the contents of the file:
2,3,4
1
2
3
4
...
21
22
23
24
Now, to read the file:
%% read the file back in MATLAB
fid = fopen('matrix.txt', 'r');
sz = str2num(fscanf(fid, '%s\n', 1)); % read dimensions
M2 = reshape(fscanf(fid, '%f\n', inf), sz); % read values
fclose(fid);
%% test the imported matrix
disp(sz)
if all(all(all(M == M2)))
disp('OK')
else
disp('Test failed.')
end
I have a file that contain the data logged of 6 experiments with this information logged "time ax ay az gx gy gz"
I will call it logmpu6050 in my specific case a 26,220X7 matrix.
I can recognize every experiment because time restart from a lower random value from the previous.
So when this condition is satisfied ti>ti+1 the data of the following experiment starts from the i+1 row.
I defined a "boundary vector" "ind" that contains all this value, and i added the first (1,1) and the last value(end,1) of the first column of the logmpu6050 matrix because are two exeption that don't satisfy the condition.
But when i want to know for example, this information:
query1=logmpu6050(ind(1),:)
Matlab gave me the values of the second row of ind, not the first, as you can see in the pic attached. Why?
I also tought it could start counting from 0, but is false, Matlab dispalys an error message with the 0 value.
Thanks, always, for your time, my civil engineer background makes hard to solve this kind of problems.
Here the code i wrote.
%Open the file
filename= uigetfile ('.txt');
fileID = fopen (filename);
logmpu6050 =csvread(filename);
fclose (fileID);
n=length(logmpu6050);
%Count every time i>i+1 and store the entire raw value
ind=find(diff(logmpu6050(:,1))<0);
ind=[logmpu6050(1,1);ind(:,:);logmpu6050(end,1)];
%No errors appear - logmpu6050 is a 26220X7 double - ind is a 7x1
ind
query1=logmpu6050(ind(1),:)
query2=logmpu6050(ind(2),:)
An alternative method could split the matrix into a cell array of submatrices:
% Generate an example
N = 3; % Num of experiments
n = randi([2,5],N,1); % Points per experiment
logmpu6050 = cell2mat(arrayfun(#(x) [(1:n(x))' x*ones(n(x),6)],1:N,'UniformOutput',0)');
% Find cut points
cuts = [diff(logmpu6050(:,1))<0;1];
% Split into a cell array
experiments = mat2cell(logmpu6050,diff([0;find(cuts)]));
Then you can access the submatrices like:
% The first experiment
experiments{1}
% The second experiment
experiments{2}
I think a lookup function would work nicely to pull out the submatrices you want.
Here's an example
% Generate an example data matrix
n = 3; % Points per experiment
N = 3; % Num of experiments
logmpu6050 = [repmat((1:n),1,N); repmat((1:n*N),6,1)]';
% Make a lookup function
lookup = #(x) cumsum([1;diff(logmpu6050(:,1))<0])==x;
% Get experiment 1 data
logmpu6050(lookup(1),:)
% Get experiment 2 data
logmpu6050(lookup(2),:)
This will output for the first experiment:
ans =
1 1 1 1 1 1 1
2 2 2 2 2 2 2
3 3 3 3 3 3 3
and for the second:
ans =
1 4 4 4 4 4 4
2 5 5 5 5 5 5
3 6 6 6 6 6 6
I have an input matrix as below
all = [12 16;12 13;8 14;14 19;3 6;8 6;13 25;25 14;7 2];
I need the following output
output = [12 16;8 14;3 6;13 25;7 2];
The explanation for the output is as follows.
First row of input i.e. 12 16 is the first row in output as both the numbers have never been repeated before in the output matrix (obviously).
Second row of input i.e 12 13 is not needed as the number 12 is present in first row of output i.e repeated
Third row of input i.e 8 14 is second row of output as both the numbers have never been repeated before in the output matrix.
Fourth row of input i.e 14 19 is not needed as the number 14 is present in output i.e repeated
On similar lines
3 6 needed as both are not repeated,
8 6 not needed as both 8 and 6 are repeated,
13 25 needed as both are not repeated
25 14 not needed as both are repeated
7 2 needed as both are not repeated
I am not able to get any ideas to start. Any help will be appreciated.
Thanks!
One Liner Solution
res = all(arrayfun(#(ii) isempty(intersect(all(1:ii-1,:),all(ii,:))),1:size(all,1)),:);
Result
res =
12 16
8 14
3 6
7 2
Explanation
let's divide the one-liner into a more detailed and documented chunk of code:
%defines a function which validates for each index wheter the row is
%completely unique are not.
uniqueRowIndicator = #(ii) isempty(intersect(all(1:ii-1,:),all(ii,:)));
%finds all the unique row in the matrix
inds = arrayfun(uniqueRowIndicator,1:size(all,1));
%extracts the result from the returned indices
res = all(inds,:);
This assumes that if a row contains two equal values they count as repeated and thus the row should be removed.
Don't use all as a variable name, because that shadows a function:
A = [12 16;12 13;8 14;14 19;3 6;8 6;13 25;25 14;7 2]; % input matrix
[~, u] = unique(A.', 'first'); % unique values of linearized transposed A.
% In recent Matlab versions you an remove 'first '
M = false(flip(size(A))); % initiallize mask of values to be kept
M(u) = true; % fill values
output = A(all(M,1),:); % keep rows that only have non-repeated values
This gives
output =
12 16
8 14
3 6
7 2
I have a matrix like this:
fd =
x y z
2 5 10
2 6 10
3 5 11
3 9 11
4 3 11
4 9 12
5 4 12
5 7 13
6 1 13
6 5 13
I have two parts of my problem:
1) I want to calculate the difference of each two elements in a column.
So I tried the following code:
for i= 1:10
n=10-i;
for j=1:n
sdiff1 = diff([fd(i,1); fd(i+j,1)],1,1);
sdiff2 = diff([fd(i,2); fd(i+j,2)],1,1);
sdiff3 = diff([fd(i,3); fd(i+j,3)],1,1);
end
end
I want all the differences such as:
x1-x2, x1-x3, x1-x4....x1-x10
x2-x3, x2-x4.....x2-x10
.
.
.
.
.
x9-x10
same for y and z value differences
Then all the values should stored in sdiff1, sdiff2 and sdiff3
2) what I want next is for same z values, I want to keep the original data points. For different z values, I want to merge those points which are close to each other. By close I mean,
if abs(sdiff3)== 0
keep the original data
for abs(sdiff3) > 1
if abs(sdiff1) < 2 & abs(sdiff2) < 2
then I need mean x, mean y and mean z of the points.
So I tried the whole programme as:
for i= 1:10
n=10-i;
for j=1:n
sdiff1 = diff([fd(i,1); fd(i+j,1)],1,1);
sdiff2 = diff([fd(i,2); fd(i+j,2)],1,1);
sdiff3 = diff([fd(i,3); fd(i+j,3)],1,1);
if (abs(sdiff3(:,1)))> 1
continue
mask1 = (abs(sdiff1(:,1)) < 2) & (abs(sdiff2(:,1)) < 2) & (abs(sdiff3:,1)) > 1);
subs1 = cumsum(~mask1);
xmean1 = accumarray(subs1,fd(:,1),[],#mean);
ymean1 = accumarray(subs1,fd(:,2),[],#mean);
zmean1 = accumarray(subs1,fd(:,3),[],#mean);
fd = [xmean1(subs1) ymean1(subs1) zmean1(subs1)];
end
end
end
My final output should be:
2.5 5 10.5
3.5 9 11.5
5 4 12
5 7 13
6 1 13
where, (1,2,3),(4,6),(5,7,10) points are merged to their mean position (according to the threshold difference <2) whereas 8 and 9th point has their original data.
I am stuck in finding the differences for each two elements of a column and storing them. My code is not giving me the desired output.
Can somebody please help?
Thanks in advance.
This can be greatly simplified using vectorised notation. You can do for instance
fd(:,1) - fd(:,2)
to get the difference between columns 1 and 2 (or equivalently diff(fd(:,[1 2]), 1, 2)). You can make this more elegant/harder to read and debug with pdist but if you only have three columns it's probably more trouble than it's worth.
I suspect your first problem is with the third argument to diff. If you use diff(X, 1, 1) it will do the first order diff in direction 1, which is to say between adjacent rows (downwards). diff(X, 1, 2) will do it between adjacent columns (rightwards), which is what you want. Matlab uses the opposite convention to spreadsheets in that it indexes rows first then columns.
Once you have your diffs you can then test the elements:
thesame = find(sdiff3 < 2); % for example
this will yield a vector of the row indices of sdiff3 where the value is less than 2. Then you can use
fd(thesame,:)
to select the elements of fd at those indexes. To remove matching rows you would do the opposite test
notthesame = find(sdiff > 2);
to find the ones to keep, then extract those into a new array
keepers = fd(notthesame,:);
These won't give you the exact solution but it'll get you on the right track. For the syntax of these commands and lots of examples you can run e.g. doc diff in the command window.
I have a text file, that is formatted somewhat like this:
1 2 3 4 5 6
7 8 9
0 11 2 32 45 6 6
1 2
I want to read each row and plot a line for each row.The x axes is [1:row.length],the y axes is each row.
fid = fopen('dat.txt');
line = fgetl(fid);
% if you want everything on the same axis, set it up here
axis([0,20,-10,10])
hold all
while ischar(line)
yy = str2num(line);
xx = 1:length(yy);
plot(xx,yy)
line = fgetl(fid);
end
hold off
fclose(fid);
Note that feof() is not so good with fgetl(), see here.
The simplest way to do it is to test for specific characters. Check for the new line character to determine if you're at the end of the current row and the end of file function to see if you're at the end of the file.
Take a look at: http://www.mathworks.com/help/matlab/ref/feof.html