MATLAB: How to change x-axis scale with dateticks - matlab

I try to plot unemployment over time but years are displayed in 10 year frequency. I want to have x-axis ticks every 5 years but can't seem to manage this as xticks are not in dateformat
Below is the relevant code if you want to take a look.
clear;
X=xlsread('UNRATE.xls');%Import Data
s_year=1950;
e_year=2015;
X=X((s_year-1948)*12+1:(e_year-1948)*12+12);
startdate = datenum('01-1950','mm-yyyy');
enddate = datenum('12-2015','mm-yyyy');
dt = linspace(startdate,enddate,792);%create numeric dates
plot(dt,X);%plot data against dates
datetick('x','yyyy');%format dates in display
recessionplot;
title('Unemployment Rate in the US over time');
xlabel('Year'); % x-axis label
ylabel('Unemployment Rate'); % y-axis label

When working with time series, the best you can do is to manually modify the XTick property of the axis so that it fits your needs once the plotting has been performed. For example:
%...
plot(dt,X);
set(gca,'XTick',datenum(1950:5:2015,1,1));
%...
Working example:
clear;
s_year=1950;
e_year=2015;
X= rand(792,1);
startdate = datenum('01-1950','mm-yyyy');
enddate = datenum('12-2015','mm-yyyy');
dt = linspace(startdate,enddate,792);
xticks = datenum(1950:5:2015,1,1);
xlabels = cellstr(num2str(year(xticks.')));
figure();
plot(dt,X);
set(gca,'XTick',xticks);
set(gca,'XTickLabel',xlabels);
Output:
Original plot without ticks adjustement:

Related

Force MATLAB to plot date gaps as zero (instead of a line gradually changing)

Everyone wants to get rid of time gaps in plot, I want them to be shown!
So I have a table in my workspace (tableM) with two variables (Date and Temperature).
Date is in the "datenum" format. I have done a lot of preprocessing on the data and had to remove many rows. Thus, I have ended up with a date variable with gaps.
When I plot the Temperature through this code: plot(tableM.Temperature), MATLAB plots the temperature normally and it just connects the two points (before the missing date with after the missing date).
When I plot temperature through this code plot(tableM.Date,tableM.Temperature) and use the datetick function, I get a plot where the date is fixed in the horizontal axis and for the date gaps, MATLAB connects the two points (before and after the missing date) with a straight line over this gap period.
What I want is to get zero for the gap period instead of this straight line connecting these points.
How do I do this?
This is the example:
% Generating data:
Date = [datenum(now-2000):datenum(now+2000)]';
Temperature = rand(4001,1); Temperature = sort(Temperature);
% Creating gaps:
Date(500:600) = []; Temperature(500:600) = [];
Date(500:600) = []; Temperature(500:600) = [];
Date(1500:2000) = []; Temperature(1500:2000) = [];
Date(1500:2000) = []; Temperature(1500:2000) = [];
% To make illustration mroe understandable:
Temperature(601:1499) = 1.8 * Temperature(601:1499);
% Normal plot:
figure; plot(Date,Temperature)
ax = gca; ax.XTickLabelRotation = -45; ax.XTick = Date(1,1):200:Date(end,1);
datetick('x',20,'keepticks','keeplimits'); ylabel('Temperature (C)'); axis tight
% Scatter plot:
figure; scatter(Date,Temperature,'.')
ax = gca; ax.XTickLabelRotation = -45; ax.XTick = Date(1,1):200:Date(end,1);
datetick('x',20,'keepticks','keeplimits'); ylabel('Temperature (C)'); axis tight
IMPORTANT: My "Date" vector is on "hourly" basis. I don't know if that creates any particular difference between the datenum values in the Date vector that could be useful.
Image1:
Normal and Scatter Plots
Image2:
Preferred Plot

Using datetick to label x axis: but don't show the last tick label

Does anyone know how to remove the last ticklabel on a plot in Matlab AFTER using the datetick function to put the labels there?
I am plotting Y data and X dates (years and months converted to a datenum).
Then I am using the following to plot the year labels on the xaxis:
close all;clear all;clc;
[num,txt,raw] = xlsread('data.xlsx');
yr = num(:,1);
mth= num(:,2);
data= num(:,3);
dates=datenum(yr,mth,1);
plot(dates,data,'r-.','linewidth',2);
dateFormat = 10;
datetick('x',dateFormat)
I would like to remove the last tick label, as it is including a year that isn't in the datset (presumably Matlab is optimising the distance between ticks and interpolating to the next year).
You should set the ticks you want on your chart first, e.g.:
set(gca, 'XTick', x_values_you_want_ticks_at);
Then use datetick with 'keepticks' option, which will preserve your ticks location:
datetick(gca, 'x', dateFormat, 'keepticks');

Create and Plot Time Series Data in Matlab

I have a (1x700) vector x for which I would like to create and plot a time series object in Matlab. Each observation corresponds to one month, and the first observation belongs to January 1960. I tried the following:
state1 = timeseries(x,1:size(x,2));
state1.Name = 'Test';
state1.TimeInfo.Units = 'months';
state1.TimeInfo.StartDate = 'Jan-1960'; % Set start date.
state1.TimeInfo.Format = 'yy'; % Set format for display on x-axis.
state1.Time = state1.time - state1.time(1); % Express time relative to the start date.
plot(state1);
However, I still see numbers on the x-axis instead of years. Could anyone please help? Thanks in advance!
Create random data. 1/12 corresponds to the fraction of a year that each month represents.
x = 1960:1/12:1970;
y = rand(1,121);
Then plot the x and y axes data using plot.
plot( x, y )
Then set the tick as follows for a decade per year. 1960:1970 will generate [1960 1961 ...] each corresponding to the tick's year.
set( gca, 'XTick', 1960:1970 );
Here is the output plot.
Doing 1 year intervals get VERY MESSY with lots of data. So solutions include doing a larger interval or setting your ticks to display vertically instead of horizontally. This code below shows how to set 5 year intervals instead.
set( gca, 'XTick', 1960:5:2010 );

MATLAB Combining Date and Hour from two cell columns

I'm trying to plot hourly data. The issue is that the date is in one column of the cell array while the hour is in the next column. How can I plot the data with the x-axis considering both the date and the hour? I'm thinking the best way would be to combine the two columns and use that as my x.
% Plot data for the month of June, 2007
% Uses the FileExchange file addaxes.m to plot 3 different y axes to
% account for the different units
clear
clc
load WI_200706_Pollution.mat;
%% Order of Columns
% 5. State Code
% 6. County Code
% 7. Site Num
% 13. Date GMT
% 14. 24 Hour GMT
% 17. Sample Measurement
%% Sort data by State Code, County Code, Site Code, Date GMT, Hour GMT
% PM25
PM25_State = sortrows(PM25,5);
PM25_County = sortrows(PM25_State,6);
PM25_Site = sortrows(PM25_County,7);
PM25_Date = sortrows(PM25_Site,13);
PM25_Hour = sortrows(PM25_Date, 14);
% SO2
SO2_State = sortrows(SO2,5);
SO2_County = sortrows(SO2_State,6);
SO2_Site = sortrows(SO2_County,7);
SO2_Date = sortrows(SO2_Site,13);
SO2_Hour = sortrows(SO2_Date, 14);
% Pull out data
PM25_data = PM25_Hour(:,17); % ug/L3
NO2_data = NO2_Hour(:,17); % ppb
CO_data = CO_Hour(:,17); % ppm
O3_data = O3_Hour(:,17); % ppm
SO2_data = SO2_Hour(:,17); % ppb
clearvars -except -regexp _data _Hour % Clear all variables except the sorted _Hour files and the _data files
%%%%%%%
%% Plot PM2.5 daily data
% Axis
DateString = PM25_Hour(2:end,11); % Pull out dates
formatIn = 'yyyy-mm-dd';
x1 = datenum(DateString,formatIn); % Convert to datnum
y1 = PM25_data(2:end); % Plot data
%% Plot SO2 hourly data
% Axis
date = datenum(SO2_Hour(2:end, 11));
hour = datenum(SO2_Hour(2:end, 12));
DateString = datenum(strcat(date, hour), 'yyyy-mm-ddHH:MM'); % Pull out dates
x5 = datenum(DateString); % Convert to datnum
y5 = SO2_data(2:end); % Plot data
% Convert cells to double
y1 = str2double(y1);
y5 = str2double(y5);
% Plot
h = figure; % To make the figure not show up, use 'h = figure('visible', 'off')';
plot(x5, y5, 'k', 'LineWidth', 1, 'Marker', 'o'); % Black line of width 2. Circular marker of color blue
addaxis(x1, y1);
addaxislabel(1,'ppb');
addaxislabel(2,'ug/CL');
grid on; % Turn on grid for plot
legend('PM2.5 (ug/CL', 'SO2 (ppb)');
The code has been shortened to include only two of the five variables I'm looking at. PM2.5 is daily data, so there's no problem with that. With SO2, I'm trying to combine the date and time under the 'Plot SO2 hourly data' part. Right now, I'm getting this error:
Error using datenum
DATENUM failed.
Caused by:
Error using dtstr2dtnummx
Failed on converting date string to
date number.
If I don't combine date and time, I get a bunch of dots going up vertically for each day. How can I still keep the x-axis daily for PM2.5, but allow the SO2 to spread out over the hours of the day?
Your date format is invalid, because 2000-12-111:00 could be 2000-12-11 at 1:00 or 2000-12-1 at 11:00. Use a separator.
If this is not the error: What is the input datenum failes at? Try dbstop if error then it stops at the right line.
Update this fixes the error, there is no reason to convert date and hour to double:
date = SO2_Hour(2:end, 11);
hour = SO2_Hour(2:end, 12);
DateString = datenum(strcat(date,'-', hour), 'yyyy-mm-dd-HH:MM'); % Pull out dates

Merge two (or more) time stamped data and plot showing the gap(s)

what is the best way to merge and plot 2 (or more) time stamped data so that the plot includes the gaps between the known data?
For example, I have a cell with time and heart rate values for Monday, and another for Friday. I would like to plot all data from Mon to Friday which includesthe gaps showing nothing was recorded from Tues-Thurs?
So far if I merge the data
data = [mon;fri]
% get the time serial numbers
dateInd = 1;
dateString = data(dateIndex);
dateFormat = 'dd/mm/yyyy HH:MM:SS';
tNum = datenum(dateString{1},dateFormat);
t = linspace(tNum(1),tNum(end),length(tNum));
% get heart rates,
HRIndex = 2;
HR = data(HRIndex);
and plot
plot(t,HR)
datetick('x','ddd');
I obviously get Monday and Fridays data merged into a single plot 2 days long. but I would like to have a plot 5 days long with data only showing on monday and Friday. What is the best way to achieve this?
I hope this makes sense,
Many thanks,
Jon
To achieve such effect I usually fill missing data with NaNs, like here:
x = linspace(0,2*pi,100);
y = sin(x);
y(20:30) = NaN; % there will be a gap from point#20 to point#30
plot(x,y);
The reason is that MatLab does not draw plot points where either x or y data are NaNs.
In your case you may add missing time points to your time data (to have corect gap) and NaNs to corresponding Y-values.
By the way, why don't you plot two separate plots with X-data of the second one properly shifted?
EDIT
Case 1: your x-data is time relative to the start of the day (in 0-24 interval). If you plot them directly they will overlap. You have to add some offset manually, like this:
% generate test data
x1 = linspace(0,1,25); % 25 points per first day
y1 = rand(25,1);
x2 = linspace(0,1,25); % 25 points per second day
y2 = rand(25,1);
% plot them as two separate plots
% so line style, color, markers may be set separately
XOffset = 3;
figure;
plot(x1,y1,'*k-', x2+XOffset,y2,'*r-');
% plot them as single separate plot
% so line style, color, markers are the same
figure;
plot([x1(:); NaN; x2(:)+XOffset],[y1(:); NaN; y2(:)],'*k-');
% One NaN is enough to insert a gap.
Case 2: your x-data have full time information including the date (like MatLab's serial date number, see help on now function, for example). Then just plot them, they will be offset automatically.
% generate test data
XOffset = 3;
x1 = linspace(0,1,25); % 25 points per first day
y1 = rand(25,1);
x2 = linspace(0,1,25)+XOffset; % 25 points per second day, with offset
y2 = rand(25,1);
% plot them as two separate plots
% so line style, color, markers may be set separately
figure;
plot(x1,y1,'*k-', x2,y2,'*r-');
% plot them as single separate plot
% so line style, color, markers are the same
figure;
plot([x1(:); NaN; x2(:)],[y1(:); NaN; y2(:)],'*k-');
% One NaN is enough to insert a gap.
Also instead of
plot(x1,y1,'*k-', x2,y2,'*r-');
you may do like this (number of plots is not limited):
hold on;
plot(x1,y1,'*k-');
plot(x2,y2,'*r-');
hold off;