Plot two x-axis in a graph with Time(calendar month/year) on axis and Hour on another x-axis

hello guys, I am facing an issue in plotting, would really appreciate if some can help/suggest any method.
I have data in 3 columns,
Column #1= Date(YYYY-MM-DD)
Column #2= Time(hr)
Column #3= Temp
I want to plot a graph with Temperature on y-axis and need to have two x-axis. One x-axis should have Time(hr) and other x-axis should have Date(YYYY-MM-DD).
At the end I want time(Hr) should match with date on the plot. Means when date is 2021-05-18 on one x-axis, time on the another x-axis should be 1000.44, as per data
I am using Matlab R2021b.
Thanks

 Accepted Answer

I'm having some trouble interpretting your data. I'm not sure I understood completely how the dates align with the times.
For example, the first data point is March 5, 2021 and 30.36361 hours and the 199th data point is March 5, 2021 and 32.82417 hours, but the 200th data point is March 10, 2021 and 57.55306 hours. More than 25 hours elapsed between March 5 and March 10, so there is some detail I'm clearly missing.
Regardless: There isn't really a great way (currently) in MATLAB to create two x-axes. You have two (not great) options:
  1. Create two overlapping axes, and make sure to align them carefully with one another.
  2. Manually position text objects to "fake" a second x-axis.
In addition, there isn't a built-in way to create a discontinuous datetime ruler (as in, a ruler that uses datetimes as input data, but has gaps in time along the ruler). The only way to recreate this would be to manually create this effect by setting the desired tick values and labels.
Here is my attempt at interpretting what you are trying to create, using the first approach (two overlapping axes):
tbl = readtable('matlabproblem.xlsx');
tbl.Time = hours(tbl.Time);
% Create a tiledlayout to keep two axes aligned with one another.
layout = tiledlayout(1,1);
% Plot the hours data.
ax1 = nexttile(layout);
plot(ax1, tbl.Time, tbl.Temp);
box(ax1,'off');
% Create a second axes for the date labels.
ax2 = axes(layout);
ax2.Layout.Tile = 1;
% Plot the same data in the second axes.
p = plot(ax2, tbl.Time, tbl.Temp);
% Make sure the two axes stay in-sync with one another.
linkaxes([ax1, ax2]);
% Hide the second axes and data, but keep the second set of rulers.
p.Visible = 'off';
box(ax2,'off');
ax2.Visible = 'off';
ax2.XAxisLocation = 'top';
ax2.XAxis.Visible = true;
ax2.YAxisLocation = 'right';
ax2.YAxis.Visible = true;
% Loop over the dates and create manual tick labels for each unique data.
alldates = unique(tbl.Date);
centers = tbl.Time(1:numel(alldates));
labels = string(alldates);
for d = 1:numel(alldates)
times = tbl.Time(tbl.Date == alldates(d));
centers(d) = mean([min(times) max(times)]);
end
xticks(ax1, centers);
xticklabels(ax1,labels);
xtickangle(ax1,45)

4 Comments

Hello Benjamin, I appreciate your answer.
Yes, data is little weird. There is elapsed time in terms of calendar day and HR as well.
Your script works well for me. I was looking for the same graph. Thanks.
Now, The probelm I am facing on x-axis is that using this script x-axis displays all the dates, thus it made graph at x-axis very hard to read.
Therefore I need X-axis to display only calendar day at the start of data, after every 500Hour and end of the Data.
Is there any way/method that could help me to graph as required. Though by using this script it seems I am very close.
It shouldn't take any major revisions to the examples script to achieve what you want.
The example script is calculating the centers and labels then calling the xticks and xticklabels functions to set which ticks are visible and what labels to use on those ticks. Small tweaks to those values should relatively easily achieve what you are looking for. The first input argument to both xticks and xticklabels is the axes to operate on. If you want to change the dates, you operate on one axes. If you want to modify the hours, you operate on the other axes.
Hello Benjamin,
I tried to modify data, but still it does not work. I can see all the dates are displayed on x-axis.
Can you please clarify what values needs to be changed? what tweaks are required to display only dates after every 500hr. any expample you can show?
Much appreciated, in advance.
Looking at the script I posted, this section calculates the ticks along the date axis:
alldates = unique(tbl.Date);
centers = tbl.Time(1:numel(alldates));
labels = string(alldates);
for d = 1:numel(alldates)
times = tbl.Time(tbl.Date == alldates(d));
centers(d) = mean([min(times) max(times)]);
end
Once that code finishes: centers is a list of duration values that correspond to where to place labels and labels is a list of strings which reflect which labels to put at each of those locations. The centers vector is in duration values that align with the top axis (which shows hours).
If you want to put date strings at different locations, all you need to do is pick where you want labels, and what labels you want at those locations. The "where" is in duration values that correspond to your time vector. You can create this vector in whatever manner you want. For example, to put a label every 100 hours:
centers = hours(0:100:1000);
The labels can be anything you want. I don't understand your data and how the dates and durations line up to be able to offer any more advice about how to label the data.
Once you've got those two vectors (which should be equal length), these two lines of code actually set the ticks labels:
xticks(ax1, centers); % Where to put the labels
xticklabels(ax1,labels); % What labels to use
If you want to change the labels along the top (hours) axis, the instructions are basically the same, except instead of ax1 you would use ax2 when you call xticks and xticklabels.

Sign in to comment.

More Answers (1)

This made little sense to me until I realized that the times were elapsed times from the beginning of data collection i hours, and not time of day. You can plot temp against a datetime variable, or against a duration variable (you may want to convert those numeric elapsed times to durations using the hours function), but not against both on the same axis. I suspect that you may end up making a plot against one or the other, and then adding the one you did not use as text.

1 Comment

hello Peter, I tried to use this code given below:
Problem with this code is that Time(HR) and calendar time(YYYY/MM/HH) on plot does not matches when I compare with actual data.
Any suggestion? There occurs some scaling issue on x-axis.

Sign in to comment.

Categories

Products

Release

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!