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

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

Related

Scatter with line segments

I really like scatter()'s ability to automatically color points based on some vector of values, I just want to add colored lines between the points.
The plot in question has time on x-axis, monte-carlo number on y-axis, and then some measured value as the color vector (e.g. number of cars seen in a video frame).
Basically, each point is an update in the system. So calling scatter(time,monte_carlo_number,[],color_vec) plots the points at which there is an update in the system, with color representing some value. This is great, but I would like to add line segments that connect these points, each segment matching the color specified by color_vec.
Basic working example
% Create example data
data = table();
data.time = randsample(1:100, 1000, true)';
data.mc = randsample(1:50, 1000, true)'; % actual monte-carlo run number labels are sorted
data.color_value = randsample(1:10, 1000, true)';
% Create the scatter plot
scatter(data.time, data.mc, [] , data.color_value, 'filled')
colorbar('Ticks', unique(data.color_value))
% Always label your axes
xlabel('Time (s)')
ylabel('Monte-Carlo Run Number')
Below is a screen-shot of what this code might produce. If color_value is the number of cars seen in a video frame, we can see each time this value is updated via the points. However, it is easier for humans to read this plot if there were lines connecting each point to the next with the correct color. This demonstrates to the viewer that this value continues on in time until the next update.
Something like this? I changed the number of samples to 100, and it is already quite a mess, so I don't think this is going to the viewer understand what's plotted.
% Create example data
data = table();
np = 100;
data.time = randsample(1:100, np, true)';
data.mc = randsample(1:50, np, true)'; % actual monte-carlo run number labels are sorted
data.color_value = randsample(1:10, np, true)';
vals = unique(data.color_value).';
cmap = parula(numel(vals));
colors = [];
for k = 1:numel(vals)
ind = find(data.color_value == vals(k));
data_sel{k} = sortrows(data(ind,:));
colors(k,:) = cmap(k,:);
end
figure(1); clf;
% Create the scatter plot
scatter(data.time, data.mc, [] , data.color_value, 'filled')
hold on
for k = 1:numel(vals)
plot(data_sel{k}.time, data_sel{k}.mc, 'Color',colors(k,:))
end
colorbar('Ticks', unique(data.color_value))
% Always label your axes
xlabel('Time (s)')
ylabel('Monte-Carlo Run Number')

MATLAB: How to change x-axis scale with dateticks

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:

Matlab, changin x-axis to date on colormap

Im trying to make a space time plot using a colormap in Matlab. On the x-axis I want time in the format 'HH:mm'. The problem is that either the plot is visible with incorrect x-axis, or the plot disappears
numberOfCells = 50;
numberOfTimeSteps = 120;
for i = 1:numberOfCells
for j = 1:numberOfTimeSteps
temp(i,j) = rand*10;
end
end
% to use this function, the array temp needs to be an array of size[rows=numberOfcells, columns=numberOfTimesteps]
% make the startTime and endTime to the strings
startTimeString = '2013-03-21 08:00:00';
endTimeString = '2013-03-21 10:00:00';
formatOut = 'HH:MM';
% convert startTimeString and endTimeString into serial date number
startTimeNum = datenum(datestr(startTimeString,formatOut));
endTimeNum = datenum(datestr(endTimeString,formatOut));
xData = linspace(startTimeNum,endTimeNum,numberOfTimeSteps/30 + 1);
% load the colormap from mycmap.mat
figure(1)
imagesc(temp);
colormap;
colorbar;
ax = gca;
ax.XTick = xData;
datetick('x',formatOut,'keepticks')
The simple solution is to set your axes directly when calling imagesc as
imagesc(xData, 1:50, temp);
You can then call datetick with no problems. The underlying problem is that images (as created by imagesc) interact a bit weirdly with figures and their associated axis in matlab. You can make the axis display the correct number by setting 'XTickLabel', rather than 'Xtick'. But when I try and convert it to a date this way they all appear as time 00:00 for some reason, which I don't understand.

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;

datetick affecting figure dimensions

I have several time series that I am trying to analyse and I am plotting all the series in different subplots and scatter plots. The date vector I have is in Julian dates, and I am having some problems in visualising the dates without it affecting the figure quality. Consider the following:
dat = 1-(20-1).*rand(365,8);
dat2 = 1-(20-1).*rand(365,8);
time = datenum('2009-01-01'):datenum('2009-12-31');
dtt = {'keepticks'};
for i = 1:8;
for ii = 1:2;
figure(ii);
ax = subplot(4,2,i);
plot(time,dat(:,i),'k');
hold on;
plot(time,dat2(:,i),'r');
if ii == 1;
datetick('x','mmm','keepticks');
else
datetick('x','mmm');
end
AX = get(ax,'position');
AX(3) = AX(3)./2;
set(ax,'position',AX);
axes('position',[AX(1)+AX(3) AX(2) AX(3) AX(4)]);
scatter(dat(:,i),dat2(:,i));
end
end
As you see, the difference between figure 1 and figure 2 is that in one I have specified to 'keepticks' (wwhich is what I would like to do), but the two final plot dimensions vary, the format of the plots should be like figure 2. Why is this happening? How could I use keepticks but also have the subplots to maintain their dimensions?