Plotting data on time (date) axis - matlab

I have data like this:
22.10.1980. 100
25.10.1980. 120
26.10.1980. 12
(only much more of it, and for each date, several independent measurements on the right).
Now, this is probably trivial, but I've never done anything like it in MATLAB, and am having problems finding similar examples online. I need to plot the data on a time/showing dates axis (x axis), with all dates inside (so, 23. and 24. as well ... for which I don't have measurements).
How can I get dates to show up on a plot axis?

It seems like it might be the best to use datetick.
Usage: datetick('x') or datetick('x', dateformat) with the available formats as explained in the documentation.

Assuming your data file has the format given above, you could use textscan to read the data:
fid = fopen('data.txt','rt');
C = textscan(fid,'%s %s %s %d','Delimiter','.','CollectOutput',1);
fclose(fid);
The first cell of C will contain an N-by-3 cell array of strings (the parts of the date) and the second cell of C will contain an N-by-1 vector of the data measurements. You can create a date number for each measurement by first concatenating the 3 smaller strings into one date string and then using the datenum function:
t = datenum(strcat(C{1}(:,3),'-',C{1}(:,2),'-',C{1}(:,1)));
data = C{2};
Once you have a vector of date numbers t to go with your vector of measurements data, you can then plot them:
plot(t,data,'*'); %# Plot the points as asterisks
Now, you can change the x-axis labels to show the actual dates. One option is to use the function datetick, an easy and elegant solution given in steven's answer. Another option is to use the function datestr to create the labels yourself, then modify the XTick and XTickLabel properties of the current axes:
xpts = min(t):max(t); %# Make a full vector, filling in missing dates
set(gca,'XTick',xpts,'XTickLabel',datestr(xpts)); %# Set axes properties
NOTE: Whichever option you choose for changing the x-axis labels to date strings, you may run into trouble with the labels overlapping each other if the tick marks are too close together. You could fix this by reducing or repositioning the tick marks along the x-axis (by changing the XTick property) or by adjusting the axes FontSize property. If you wanted to rotate the labels to make them fit, you would have to erase the labels and create new rotated text objects for them. The following submission on The MathWorks File Exchange does just that:
Rotate Tick Label by Andrew Bliss

With datenum you can convert any string date into numerical format based on the date format symbols (see help datestr).
For example all this leads to the same numerical date representation:
datenum('15/05/2009 21:22','dd/mm/yyyy HH:MM');
datenum('15.05.2009 21:22','dd.mm.yyyy HH:MM');
datenum('21-22 15.05.2009','HH-MM dd.mm.yyyy');
datenum('21-22 05/15.2009','HH-MM mm/dd.yyyy');
...
The nice thing is that you can pass cell array (output from textscan) or char array directly to datenum and it will output numeric date array.

Datetick is a good option, as well as datetick2, which can be found here: MATLAB Central
Datetick2 allows panning and zooming, with adjustments to the time labels, depending on how far you're zoomed in.
I'm not sure about the dd.mm.yyyy format - you could use regexp or strrep to change the decimals to dashes if neccessary.

You can use datenum to convert the dates to a numbers, and plot the data as usual. lets say you put your dates vector in the variable called x.
Now, you can use
set(gca, 'xtick',x(1:10:end));
set(gca, 'xticklabel',datestr(x(1:10:end));
to set the ticks on the x axis.

Related

For a time series plot, how to set the x axis to calendar time without weekends

I want to plot a time series (pricing data for a forex future contract). Time is given in yyyymmdd HH:MM:SS string format. Price is in double.
The time series spans over a week. However, the timestamp for the data points are always on weekdays. Is there a built-in method to display the appropriate x-axis labels and scaling but without weekends?
I can currently display the time series by converting the timestamp in string to datenum and arrange x-axis automatically with datetick. But I would like to know how to exclude weekends on the x-axis. Or exclude any extended interval of time from the grid where there is no data.
For a visual, please see example at the end. If one can exclude the large empty space due to including the weekend (Apr 10 was a US holiday), the plot can become more legible by focusing on where there is actually data.
The data points themselves are exclusive to weekdays. But between plot and datetick, grid points on weekends are created whenever the time series spans over a week. datetick is helpful because it detects the appropriate scaling for x-axis grid and applies the corresponding grid labels all in one go. If you see datetick as a part of the solution, is there a way to remove particular grid points after using datetick?
Example:
T=[7.378903958333334e+05;7.378967076388889e+05]; % converted from "20200409 09:30:00" and "20200415 16:59:00"
C=[0.7166;0.7090];
grid on
plot(T,C,'.')
xlim([min(T),max(T)])
datetick
If you are interested in tinkering with the same plot, please retrieve the data by c&p into Matlab cmd from pastebin. The same lines above will produce the following plot.
There is no such features. Probably, because this essentially makes the x-axis discontinuous, which is (usually) not desirable.
You will have to create a synthetic x-axis to achieve this by sorting out the the weekends (or rather the not business days).
This is the standard plot (the business days are blue)
% create data
T = 7.3789e+05+(0:5:100)/10.';
C = rand(size(T));
% is a busniess day?
lg = isbusday(T);
% standard date plot
plot(T(lg),C(lg),'o', T(~lg),C(~lg),'o')
datetick('x','ddd')
Now let us get rid of the other days and set the xTickLabel manually:
T = T(lg);
C = C(lg);
% plot without time-axis
plot(C,'o')
% --- get ticks
xTick = get(gca,'XTick');
% get which ticks are integers
lg = isreal(xTick) & rem(xTick,1)==0;
XTick_new = xTick(lg);
% --- create new tick label
xTickLbl_new_num = NaN(size(XTick_new));
% make sure they are within the limits
lg = XTick_new >= 1 & XTick_new <= length(T);
xTickLbl_new_num(lg) = T(XTick_new(lg));
% convert to string (arbitrary format)
xTickLbl_new_str = strings(size(xTickLbl_new_num));
xTickLbl_new_str(lg) = datestr(xTickLbl_new_num(lg),'ddd');
% set new label
set(gca,'XTick',XTick_new,'XTickLabel',xTickLbl_new_str);
Have a look on the results: left the standard version and on the right the version with manually set tick-labels.

matlab - get date in month/year format from datenum number format

I have a table which contains the year and the month in a "double" format.
I then create a datenum for each entry in the table:
for j=1:number_of_rows
dates_returns_all_period_monthly(j,10)=datenum([year,month,1]);
end
First of all, is there a way to have the dates on a monthly basis without having to set the day on the datenum command?
Secondly, the previous commands give me values such as 731947 for
I then want to get the date in a date format,
I am trying to run the following command:
dates_returns_all_period_monthly(j,11)=datestr(dates_returns_all_period_monthly(j,10));
but I get an error "Assignment has more non-singleton rhs dimensions than non-singleton subscripts"
How can I fix this? Ideally I would like to have something like January 2004, February 2005, etc.. or 01/2004, 02/2004, something like that, because later on I want to plot with the dates on the x-axis, and I don't want to have 731947 etc. as values.
The problem here is that you are trying to put a string output into a matrix array. This won't work: it will try and convert the string to an array of numbers, and your indexing will tell it to try to put your array of numbers into a single matrix location, causing the error that you are seeing.
What you'll need to do if you wish to store them is to create a cell array, which store arbitrary data inside each element location, but require different syntax to access:
text_dates = cell(1,number_of_rows);
for j=1:number_of_rows
text_dates{j}=datestr(dates_returns_all_period_monthly(j,10));
end
You won't be able to use these directly as part of the plot command however - Matlab needs inputs to plot to be numeric, so strings will not work. What you want to do is create your plot using your numeric values, then access the current axis properties (you can use the gca command to get this) and change the `XTickLabel' properties to the strings you wish, e.g.:
plot(dates_returns_all_period_monthly(:,10),whatever_your_y_values_are);
ax=gca;
set(gca,'XTickLabels',text_dates);

Converting from datenum back to actual time

Ok, so I've been messing with what should be a simple problem. I'm trying to plot an numerical array (double) vs. the associated time stamp (cell) with the format of the DD-MM-YY HH:MM:SS (for example: 13-Mar-15 07:23:10).
I'm able to plot a single set using datetime(time stamp). Due to the data set it outputs the nice HH:MM on the x-axis. Very nice.
Now in order to plot 2 sets of values on the same graph, I've found that Matlab doesn't like to use the date_time twice for the x-axis, so then I go to the infamous datenum function, which is able to plot both on the same graph. However, it's in the serial value of time and it jacks with my plot sizing (i.e. the x-axis doesn't autosize).
With what should be a simple problem has actually caused me days scouring the internet trying to reconvert it back to my beloved HH:MM after converting the "time stamp" into the serial time.
I don't think that a code sample or data set should be necessary for example purposes. (but can provide if needed)
I've tried to use the datetick function, but can't get seem to get it working.
The trick with datenum and datetick is to set limits and tick positions before you call datetick, then make sure it doesn't redo them.
So, after plotting your two sets of data against the datenums it would go something like:
step = 1/24; % for hourly - adjust to preference
ticks = datenum('mystarttime'):step:datenum('myendtime')
set(gca,'XTick',ticks)
datetick('x','HH:MM','keepticks','keeplimits')
I work a lot with time series and most often I have to plot my data versus time/date.
Since Matlab never gave me a definitively convenient solution, for many years now I work this way:
I defined once and for all a Matlab shortcut (in the matlab shortcut toolbar):
containing the following code:
xticktemp = get(gca,'Xtick') ;
ticklabel = {datestr(xticktemp(1)) datestr(xticktemp(2:end),15) } ;
set(gca,'Xticklabel',ticklabel)
clear xticktemp ticklabel
I convert all my times with datenum and use this format for working (or posix time when more convenient, but it's another story), calculating and plotting. When I need to now exactly the time of an event in a human readable format, I press the shortcut and I obtain something like:
Of course there are 2 major limitations with this method:
This does not control the steps of the ticks (it just replicate what Matlab initially set)
You have to re-click your shortcut to refresh the tick labels everytime you zoom or pan the figure
For these reasons, when I need to finalize figure for presentation to others I won't use this trick and define my ticks exactly like I want them, but when you are simply working away, this shortcut has saved me hours (may be even days?) of fiddling around over the last 10 years ....

Plotting in matlab time in secs as HH:MM:SS.FFF

I have a 356*2 array lets call him tmp
When the (:,1) is in milisecs
Now i am looking to make a plot of X over y when i want the X be showed in HH:MM:SS.FFF secs
I have converted the secs to that format by
datestr(tmp(:,1)*0.001/24/3600,'HH:MM:SS.FFF')
But this is a string, how can i use it in my plot function
You can apply what are called date format strings to the axes of plots with built-in function datetick. For example, with your first column being time, you could call
plot(tmp(:, 1), tmp(:, 2))
to plot the data. Then call:
datetick('x', 'HH:MM:SS.FFF')
to format the values assigned to ticks on the x-axis based on the second input argument. NOTE that, in order to perform this conversion, the function assumes that the time data is in units of DAYS, so if your data is in milliseconds, you should divide your time data by (24*60*60*1000). Note also that when you zoom on this graph, the new labels will not be re-written at each scale as numeric ones would have been. To get around this, I thoroughly recommend datetickzoom from the MATLAB file exchange.
Use your original value of tmp(:,1) for the plot function and then use your datestr(tmp(:,1)*0.001/24/3600,'HH:MM:SS.FFF') as the label?

Plot against time of format "hh:mm:ss" in MATLAB?

I have a bunch of time-indexed data, that I have to plot with MATLAB.
The current format of the time is as follows
23:55:42,-147928.686833054
23:55:43,-147928.404621219
23:55:44,-147928.219419702
23:55:45,-147928.395802099
23:55:46,-147928.492812417
23:55:47,-147928.413440339
23:55:48,-147928.386982979
I simply wish to plot the second column, the values, against the first column, the time.
I can of course take the first time point as 0, and next as 1, ..., and so on. However, I wish to stick with the original timing.
How may I deal with this type of time handily?
Convert your time values using datenum. Create an X-Y plot in the usual way. And ask for time-formatted labels with
datetick('x', 13)
For example:
plot(datenum(a(:,1)), a(:,2));
datetick('x', 13)
Try the property "XTickLabel" after plotting.
You can use it with a cell of strings of your data:
plot(second-column-values)
Times={'23:55:42','23:55:43',...}
set(gca,'XTickLabel',Times)