using datenum results in not showing both strings - matlab

1. How do I read in this data properly so that the date parses properly?
I am trying to concatenate strings I read from a file but the output I get is mixed up.
The output is the x axis.Also, the spacing from x axis has numbers instead of the string I want.
The file has 4 columns,date,time,temperature and value.
The date is "01.01.2013 " and the time "09:08:02"
Also, if I want to use only first column (with date) how can I do this?
Because using datenum(mydata{1}) results to "Cannot parse date 01.01.2013"
...
mydata = textscan(fid, '%s %s %f %f', 'delimiter',';', 'HeaderLines',1);
date={};
temp={};
..
date{1}=datenum( strcat(mydata{1},{' '},mydata{2}) );
...
2. How do I correct the axis ticks?
I am then trying to plot data using plotyy and want the x-axis to be the date, but I am getting two different axis labels.
Here is the code I am using:
temp = mydata{4};
plotyy(date,temp,date,2*temp);
datetick('x','mmm.dd,yyyy');
Here is the resulting image:
---------------UPDATE---------------------------------------
Here is the code:
fid = fopen('test2.txt','r');
mydata = textscan(fid, '%s %s %f %f', 'delimiter',';', 'HeaderLines',1);
fclose(fid);
date=datenum( strcat(mydata{1},{' '},mydata{2}),'mmm.dd,yyyy HH:MM:SS' );
temperature=mydata{3};
value=mydata{4};
[AX,H1,H2]=plotyy(date,temperature,date,value,'plot');
set(get(AX(1),'Ylabel'),'String','Temperatures');
set(get(AX(2),'Ylabel'),'String','Value');
set(H1,'LineStyle','--');
set(H2,'LineStyle',':');
datetick(AX(1),'x','mmm.dd,yyyy');
title('Temperatures - Values');
xlabel('Date')
and the file
Date;Time;Temp;value
Jan.01,2013; 11:00:00;20;10
Feb.08,2013; 12:00:00;23;11
Mar.04,2013; 04:02:00;24;15
Apr.10,2013; 08:04:00;28;20
May.10,2013; 12:05:00;32;30
Jun.04,2013; 10:06:0;33;27

1. Parsing input
You are receiving the "cannot parse" error, because you are also not including a format string (formatIn). See the documentation for datenum.
If you want to convert only the first column to the date, this would look like:
date=datenum(mydata{1},'mm.dd.yyyy');
If you want to convert both the first and second columns, try:
date=datenum( strcat(mydata{1},{' '},mydata{2}),'mm.dd.yyyy HH:MM:SS');
Here is the entire code I am running, which seems to work. Note that there is no header row in my datafile.
% data.txt
% 01.01,2013; 11:00:47;10;20
% 01.02,2013; 11:00:57;10;40
fid = fopen('data.txt');
mydata = textscan(fid, '%s %s %f %f', 'delimiter',';');
date=datenum( strcat(mydata{1},{' '},mydata{2}),'mm.dd,yyyy HH:MM:SS');
2. Getting correct plots
There are two different x-ticks for plotyy command. By setting datetick in the way you did, you are only changing one of them. Instead, change first x-tick to date tick and set the second x-ticks to empty.
temp = mydata{4};
[AX,H1,H2] = plotyy(date,temp,date,2*temp);
datetick(AX(1),'x','mmm.dd,yyyy');
set(AX(2),'XTick',[])

Related

Plot in MATLAB using data from a txt file

I need to read data from a file and plot a graph with its data. The problem is:
(1) I can't change the format of data in the file
(2) The format contains information and characters that I don't know how to deal with.
Here is a part of the data file, it's in a txt format:
Estation;Date;Time;Temp1;Temp2;Pressure;
83743;01/01/2016;0000;31.9;25.3;1005.1;
83743;01/01/2016;1200;31.3;26.7;1005.7;
83743;01/01/2016;1800;33.1;25.4;1004.3;
83743;02/01/2016;0000;26.1;24.2;1008.6;
What I'm trying to do is to plot the Date and Time against Temp1 and Temp2, not worrying about Pressure. The first column can be neglected as well. How can I extract the Date, Time and Temps into and matrix so I can plot them? All I did so far was this:
fileID = fopen('teste.txt','r');
[A] = fscanf(fileID, ['%d' ';']);
fclose(fileID);
disp(A);
Which just reads the first value, 83743.
To build on m7913d's answer:
fileID = fopen('MyFile.txt','r');
A = fscanf(fileID, ['%s' ';']); % read the header line
B = fscanf(fileID, '%d;%d/%d/%d;%d;%f;%f;%f;', [8,inf]); % read all the data into B (the date is parsed into three columns)
fclose(fileID);
B = B.'; % transpose B
% C is just for verification, can be omitted
C = datetime([B(:,4:-1:2) B(:,5)/100zeros(numel(B(:,1)),2)],'InputFormat','yyyy-MM-dd HH:mm:ss');
D = datenum(C); % Get the date in a MATLAB usable format
Titles = strsplit(A,';'); % Get column names
figure;
hold on % hold the figure for multiple plots
plot(D,B(:,6),'r')
plot(D,B(:,7),'b')
datetick('x') % Set a date tick as axis
legend(Titles{4},Titles{5}); % uses titles for legend
note the parsing of the date into C: first is the date as given by you in dd-MM-yyyy format, which I flip to the official standard of yyyy-MM-dd, then your hour, which needs to be divided by 100, then a 0 for both minutes and seconds. You might need to rip those apart when you don't have exactly hourly data. Finally transform to a regular datenum, which MATLAB can use for processing.
Which results in:
You might want to play around with the datetick format, as it's got lots of options which might appeal to you.
fileID = fopen('input.txt','r');
[A] = fscanf(fileID, ['%s' ';']); % read the header line
[B] = fscanf(fileID, '%d;%d/%d/%d;%d;%f;%f;%f;', [8,inf]); % read all the data into B (the date is parsed into three columns)
fclose(fileID);
disp(B');
Note that %d reads an integer (not a double) and %f reads a floating point number.
See fscanf for more details.

Matlab reading txt formatted file

If there is a .txt file in the format
Name, Home, 1, 2, 3, 3, 3, 3
It means the first two columns are string, and the rest are integers
How do I read first two column as vectors of strings, and another matrix as numeric values.
One way of doing this so you know exactly what's happening line by line is in the following piece of code:
fid = fopen('textfile.txt');
clear data
tline = fgetl(fid);
n = 1;
while ischar(tline)
data(n,:) = strsplit(tline(1:end),', ');
n=n+1;
tline = fgetl(fid);
end
fclose(fid);
dataStrings = data(:,1:2);
dataValues = str2double(data(:,3:end));
where data contains everything in string type, dataStrings contains only first 2 columns as strings, and dataValues contains the rest of the columns as type double.
This way you get simple matrices, meaning you don't have to worry yourself with structures or cell arrays.
Use textscan:
fileID = fopen('sometextfile.txt');
C = textscan(fileID,'%s %s %f %f %f %f %f %f','Delimiter',','); % assuming you want double data types, change as required
fclose(fileID);
celldisp(C) % C is a cell array

Reading CSV with mixed type data

I need to read the following csv file in MATLAB:
2009-04-29 01:01:42.000;16271.1;16271.1
2009-04-29 02:01:42.000;2.5;16273.6
2009-04-29 03:01:42.000;2.599609;16276.2
2009-04-29 04:01:42.000;2.5;16278.7
...
I'd like to have three columns:
timestamp;value1;value2
I tried the approaches described here:
Reading date and time from CSV file in MATLAB
modified as:
filename = 'prova.csv';
fid = fopen(filename, 'rt');
a = textscan(fid, '%s %f %f', ...
'Delimiter',';', 'CollectOutput',1);
fclose(fid);
But it returs a 1x2 cell, whose first element is a{1}='ÿþ2', the other are empty.
I had also tried to adapt to my case the answers to these questions:
importing data with time in MATLAB
Read data files with specific format in matlab and convert date to matal serial time
but I didn't succeed.
How can I import that csv file?
EDIT After the answer of #macduff i try to copy-paste in a new file the data reported above and use:
a = textscan(fid, '%s %f %f','Delimiter',';');
and it works.
Unfortunately that didn't solve the problem because I have to process csv files generated automatically, which seems to be the cause of the strange MATLAB behavior.
What about trying:
a = textscan(fid, '%s %f %f','Delimiter',';');
For me I get:
a =
{4x1 cell} [4x1 double] [4x1 double]
So each element of a corresponds to a column in your csv file. Is this what you need?
Thanks!
Seems you're going about it the right way. The example you provide poses no problems here, I get the output you desire. What's in the 1x2 cell?
If I were you I'd try again with a smaller subset of the file, say 10 lines, and see if the output changes. If yes, then try 100 lines, etc., until you find where the 4x1 cell + 4x2 array breaks down into the 1x2 cell. It might be that there's an empty line or a single empty field or whatever, which forces textscan to collect data in an additional level of cells.
Note that 'CollectOutput',1 will collect the last two columns into a single array, so you'll end up with 1 cell array of 4x1 containing strings, and 1 array of 4x2 containing doubles. Is that indeed what you want? Otherwise, see #macduff's post.
I've had to parse large files like this, and I found I didn't like textscan for this job. I just use a basic while loop to parse the file, and I use datevec to extract the timestamp components into a 6-element time vector.
%% Optional: initialize for speed if you have large files
n = 1000 %% <# of rows in file - if known>
timestamp = zeros(n,6);
value1 = zeros(n,1);
value2 = zeros(n,1);
fid = fopen(fname, 'rt');
if fid < 0
error('Error opening file %s\n', fname); % exit point
end
cntr = 0
while true
tline = fgetl(fid); %% get one line
if ~ischar(tline), break; end; % break out of loop at end of file
cntr = cntr + 1;
splitLine = strsplit(tline, ';'); %% split the line on ; delimiters
timestamp(cntr,:) = datevec(splitLine{1}, 'yyyy-mm-dd HH:MM:SS.FFF'); %% using datevec to parse time gives you a standard timestamp vector
value1(cntr) = splitLine{2};
value2(cntr) = splitLine{3};
end
%% Concatenate at the end if you like
result = [timestamp value1 value2];

fscanf file read in matlab for mixed numeric and non-numeric data (textscan not available)

I am trying to read a data file but I have an older version of Matlab that does not include textscan. I am trying to use fscanf but I am unable to figure out how to read the second element which is time format. The txt data looks like this:
20120502,16:30:00,1397.5,1397.5,1397.0,1397.5,1283
20120502,16:32:00,1397.25,1397.5,1397.0,1397.0,582
I have tried this, with different attempts at figuring out the 2nd column which is the time vector, but I am not having any luck.
fid = fopen('C:\matlab\data\GLOBEX.txt','r');
[c] = fscanf(fid, '%f %s %f %f %f %f %f');
Thanks
Try the following:
[c] = fscanf(fid, '%f,%d:%d:%d,%f,%f,%f,%f,%f');
c = reshape(c, 9, length(c)/9)';
Now you have hours, minutes, and seconds in columns 2, 3, and 4.

matlab exporting data

I have a daq card from which data is continuosly acquired every 100 ms. Now I want to create a txt file which contains all the data. This txt file should also have a time
stamp and should have 5 column headers - zeit , channel1, channel2.... channel4.
This is the code I could write but I am confused how to print the data after the headers.
Also after every 100 ms secs new data comes in and this has to be appended to the end of the file .The time stamp is in a specific format because later I need to search for a number.
% Time stamp
A = datestr(now, 'mmmm dd, yyyy HH:MM:SS.FFF ')
format short g
datevec(A)
fid = fopen('acq.txt','w');
fprintf(fid,'%s\t',A)
A = 'Zeit';
dataName = 'channel';
fid = fopen('acq.txt','w');
fprintf(fid,'%s\t',A)
%# loop to write the rest of the header
x=5
for iModel = 1:x
fprintf(fid,'%s_%i\t',dataName,iModel);
end
data = rand( 10,10);
fprintf( 'acq.txt' , '%i' ,data);
If you dont close the file, there is no reason to open it twice. Two consecutive fprintfs would get you started after the first fopen:
fprintf(fid,'%s\t',datestr(now, 'mmmm dd, yyyy HH:MM:SS.FFF '))
fprintf(fid,'%s\t%s1\t%s2\t%s3\t%s4\t','Zeit',dataName,dataName,dataName,dataName)
to set up the headers. At this point remember to use fclose(fid). You can now loop through each time your data is read, and open the file for append fida = fopen('acq.txt','a'); followed by formatted data output:
fprintf(fida,'%f %f %f %f %f %f %f %f %f %f\n',data')
For some reason matlab displays the data in the first row first, so transposing it puts it in the same shape as the data as represented in matlab. Remember to close these files or you might run into errors.