In the following example I have two years worth of data denoted by data_2007 and data_2008 which have a corresponding array of dates:
clear all
DateTime_2007 = datestr(datenum('2007-01-01 00:00','yyyy-mm-dd HH:MM'):1/24:...
datenum('2007-12-31 23:57','yyyy-mm-dd HH:MM'),...
'yyyy-mm-dd HH:MM');
DateTime_2007 = cellstr(DateTime_2007);
DateTime_2008 = datestr(datenum('2008-01-01 00:00','yyyy-mm-dd HH:MM'):1/24:...
datenum('2008-12-31 23:57','yyyy-mm-dd HH:MM'),...
'yyyy-mm-dd HH:MM');
DateTime_2008 = cellstr(DateTime_2008);
data_2007 = 1 + (20-1).*rand(8760,1);
data_2008 = 1 + (20-1).*rand(8784,1);
I would like to plot the data on one graph, showing how the data has varied over the 2 years, so basically a plot extending over 2 years. How can this be achieved, considering that I need the dates to be shown along the xaxis, and possible only the month name (mmm) to be given (not yyyy-mm-dd HH:MM).
Have you tried the datetick command to label the axes?
plot(datenum(DateTime_2007),data_2007)
hold on
plot(datenum(DateTime_2008),data_2008,'g')
datetick('x','mmm')
It might be easier if you didn't convert your dates to date strings, and then have to convert them back for plotting.
Use datetick. Your dates should just be datenum:
DateTime_2008 = datenum('2008-01-01 00:00','yyyy-mm-dd HH:MM'):1/24:...
datenum('2008-12-31 23:57','yyyy-mm-dd HH:MM');
and you can plot it like:
plot([DateTime_2007 DateTime_2008], [data_2007; data_2008]);
datetick('x');
If you want a different format for the ticks, try:
datetick('x', 'yyyy-mm');
and if you want to choose the location of the ticks yourself (to actually specify the ticks, you might need to use set(gca, 'XTick', ...), see axes properties):
datetick('x', 'keepticks');
Related
I want to plot a line chart that the x-axis is datetime. But there is a weekend gap in the chart. I wonder how can I remove the gaps of the weekends.
figure
plot(data.DateTime(1:833),data.diff(1:833),'b');
hold on
plot(data.DateTime(834:970),data.diff(834:970),'r');
hold on
plot(data.DateTime(971:1546),data.diff(971:1546),'b');
hold off
You can use weekday to filter your date to only include values for days of the week that aren't 6 or 7 (Saturday or Sunday)
days = datetime(2021,5,0:31);
days_weekdays_only = days(and(weekday(days)~=1,weekday(days)~=7));
This will filter the days data to only contain dates that are Mon-Fri.
Then plot this filtered data.
Edit: You can plot the values against an index of the filtered data and then change the x-axis labels to match the datetime string. This way it will skip the weekends but the x-axis will still show the date time.
days = datetime(2021,5,0:31);
weekdays = days(and(weekday(days)~=1,weekday(days)~=7));
data = randi(5,length(days),1);
data_weekdays = data(and(weekday(days)~=1,weekday(days)~=7));
idx = 1:length(weekdays);
plot(idx,data_weekdays)
set(gca,'XTickLabel',datestr(weekdays));
First of all, I think the answers I've found are outdated:
Excluding weekend gaps from financial timeseries plots
Exclude Date Gaps in Time Series Plot in Matlab
Datetick take into account NaN in plot
My problem:
I've created a candlestick graph based on a Timetable table with these dates (the format is dd/mm/yyyy):
'25/01/2019'
'24/01/2019'
'23/01/2019'
'22/01/2019'
'21/01/2019'
'18/01/2019'
'17/01/2019'
'16/01/2019'
'15/01/2019'
'14/01/2019'
'11/01/2019'
'10/01/2019'
'09/01/2019'
'08/01/2019'
'07/01/2019'
'04/01/2019'
'03/01/2019'
'02/01/2019'
'28/12/2018'
'27/12/2018'
'26/12/2018'
'21/12/2018'
'20/12/2018'
'19/12/2018'
'18/12/2018'
And this code:
candle(this.values);
This gives me this plot:
As you can see, there are gaps corresponding to the non-business days.
Given the answers that I've found to the same problem what I did was:
Created two arrays one with the dates and the other with dates strings:
this.dates = table2timetable(ticker(1:5:25,:));
%sort them out because were generated in reverse order
this.dates = timetable2table(sortrows(this.dates(:,1)));
this.dates = this.aux(:,1);
this.lbl = datestr(this.aux{:,1},'dd/mm/yyyy');
Obtain the gca object to set the X-axis properties:
this.ax = gca;
this.ax.XTick = this.dates{:,1};
this.ax.XTickMode = 'manual';
this.ax.XTickLabel = this.lbl;
And the result is this:
So the properties are being set correctly but the gaps remain.
Finally I've tried to set the Timetable property VariableContinuity and called the retime function to generate the missing dates entries with NaN data to see if that helped but with the same results:
this.values.Properties.VariableContinuity = {'event','event','event','event','event','event','event','event'};
this.values = retime(this.values,'daily');
What else could I do to hide the gaps?
I believe that once plotted, you cannot remove the gaps. You have to remove the gaps before plotting. In your timetable, create a linear date array (no gaps) and use this for the timetable, then plot. Then, the gaps will not be there but the dates will be wrong. To put the right date, use the following code (similar to your code).
this.ax.XTickMode = 'manual';
this.ax.XTickLabel = YOUR_CORRECT_DATE_CELL_ARRAY
I have a two column data with mmyyyy and SPI (Standardized Precipitation Index) variables. The first two samples have no data (NAN). The file is:
011982 NAN
021982 NAN
031982 -1.348
.
.
.
122013 1.098
I load the time and SPI data into MATLAB, then I would like to plot it but it is not working.
I would like to plot line graph but I really have no idea how to plot time in x-axis and I would like my x-axis to show only the year.
Using the new datetime data type in MATLAB (added in R2014b), this should be easy.
Here is an example. First we load the data into a MATLAB table:
% import data from file
fid = fopen('file.dat', 'rt');
C = textscan(fid, '%{MMyyyy}D %f');
fclose(fid);
% create table
t = table(C{:}, 'VariableNames',{'date','SPI'});
You get something like this:
>> t(1:10,:)
ans =
date SPI
______ ________
011982 NaN
021982 NaN
031982 2.022
041982 1.5689
051982 0.75813
061982 -0.74338
071982 -1.7323
081982 -2.4466
091982 -0.86604
101982 0.085698
Next to plot the data with date and time, it's as easy as calling plot:
plot(t.date, t.SPI)
xlabel('Date'), ylabel('Standardized Precipitation Index')
By default, plot chooses tick mark locations based on the range of data. When you zoom in and out of a plot, the tick labels automatically adjust to the new axis limits.
But if you want, you can also specify a custom format for the datetime tick labels. Note that when you do this, the plot always formats the tick labels according to the specified value, they won't adjust on zoom:
plot(t.date, t.SPI, 'DatetimeTickFormat','yyyy')
I'm adding another answer that works in older MATLAB versions without table or datetime data types.
Like before, we first import the data from file, but this time we read the dates as strings then convert them to serial date numbers using datenum function (defined as the number of days since "January 0, 0000"):
% import data from file
fid = fopen('file.dat', 'rt');
C = textscan(fid, '%s %f');
fclose(fid);
% create matrix
t = [datenum(C{1},'mmyyyy') C{2}];
The data looks like this:
>> format long
>> t(1:10,:)
ans =
1.0e+05 *
7.239120000000000 NaN
7.239430000000000 NaN
7.239710000000000 0.000005606888474
7.240020000000000 0.000009156147863
7.240320000000000 0.000004504804864
7.240630000000000 0.000008359005819
7.240930000000000 0.000007436313932
7.241240000000000 0.000002800134237
7.241550000000000 0.000005261613664
7.241850000000000 0.000001809901372
Next we plot the data like before, but instead we use the datetick function to format the x-axis as dates ('yyyy' for years):
plot(t(:,1), t(:,2))
datetick('x', 'yyyy')
xlabel('Date'), ylabel('Standardized Precipitation Index')
Unfortunately the tick labels will not automatically update when you zoom in and out... The good news, there are solutions on the File Exchange that solve this issue, for example datetickzoom and datetick2.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Calculations of files
Day price1 price2
2/2/2000 10 15
3/2/2000 12 18
4/2/2000 14 19
How could I plot x=day and y=price1?
file = xlsread('example.xls');
x = file(:,1);
y = file(:,2);
plot(x,y);
It doesn't give the days in x line it gives numbers 0, 1, 2 insted of 2/2/2000
The neatest method for getting the x-axis to display dates is via the datetick function. I used to do it manually, as the other answers to this question suggest doing, until I discovered this wonderful function.
Cut and paste the following example into a Matlab script and run it line-by-line:
y = randn(4, 1); %# Simulate random observations
Dates = {'1/1/2000', '2/1/2000', '3/1/2000', '4/1/2000'}; %# Build a vector of date strings
DatesNum = datenum(Dates, 'dd/mm/yyyy'); %# Convert date strings to date numbers
plot(DatesNum, y); %# Plot the data
datetick('x', 'dd/mm/yyyy'); %# Convert date numbers on plot to string format
The last line essentially says "on the x axis of the current plot, display the numbers in date-time format, using the format string dd/mm/yyyy".
Once you are familiar with how this example works, you should be able to adapt this example to your code.
You can use date strings to label your xtick marks in the plot. First we need to convert the date number to a date sting, using datestr.
[file, text] = xlsread('example.xls');
x = file(:, 1);
y = file(:, 2);
x0 = datenum(2000, 2, 2);
cal = cellstr(datestr(x + x0));
Then we can plot and label the tickmarks.
plot(x, y);
set(gca(), 'xtick', 1 : length(y), 'xticklabel', cal);;
If you do not have an Excel COM server available (likely the case if you are running on unix/linux), the dates will appear as Excel serial date numbers (an integer). These are different from MATLAB date serial numbers. They can be converted using x2mdate():
file = xlsread('example.xls')
file(:,1) = x2mdate(file(:,1))
set(gca,'Xtick',file(:,1),'XTickLabel',datestr(file(:,1)))
Here I am assuming that the dates in your date column are formatted as dates by Excel/LibreOffice and not as strings.
I have the following code for producing a plot of data that extends two years in terms of day of year:
time = datenum('2008-04-17 02:00'):datenum('2009-11-24 12:27');
dateV = datevec(time);
for i = 1:length(time);
DOY(i) = time(i) - datenum(dateV(i,1),0,0);
end
data = rand(length(time),1);
plot(time,data);
set(gca,'XTick',floor(time(1:50:end))','XTickLabel',floor(DOY(1:50:end)))
Could someone suggest a method for ensuring the ticks on the xaxis are for day numbers that are multiples of 10 i.e. 110, 160 etc.
ADDED SECTION:
DateTime=datestr(datenum('2007-01-01 00:00','yyyy-mm-dd HH:MM'):1/24:...
datenum('2011-12-31 23:00','yyyy-mm-dd HH:MM'),...
'yyyy-mm-dd HH:MM');
time = datenum(DateTime,'yyyy-mm-dd HH:MM');
dateV = datevec(time);
for i = 1:length(time);
DOY(i) = time(i) - datenum(dateV(i,1),0,0);
end
data = rand(length(time),1);
plot(time,data);
mydays = ~mod(floor(DOY),40); %true for days that are multiples of 10
set(gca,'XTick',floor(time(mydays))','XTickLabel',floor(DOY(mydays)))
Error using set
Values must be monotonically increasing
This can be fixed by removing floor, i.e.
set(gca,'XTick',time(mydays),'XTickLabel',floor(DOY(mydays)))
But it generates the labels in bold, why is this?
You can generate an index to days that are multiples of N using the mod function. This function returns you the remainder after dividing a number by N.
mydays = ~mod(floor(DOY),10); %true for days that are multiples of 10
data = rand(length(time),1);
plot(time,data);
set(gca,'XTick',time(mydays),'XTickLabel',floor(DOY(mydays)))
In your case having each multiple of 10 would lead to too many labels on the x-axis, so maybe try multiple of 40, which produces the following: .
Finally, if you want to change the axis labels so that it is no longer in bold, you can use:
set(gca, 'FontWeight', 'normal');
or similarly you can alter its size and font:
set(gca, 'FontSize', 14, 'FontName', 'Calibri')
EDIT: corrected typo in previous code, and added note on altering label font