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

19 visualizzazioni (ultimi 30 giorni)
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

Risposta accettata

Benjamin Kraus
Benjamin Kraus il 14 Mar 2022
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 Commenti
Harsimran Singh
Harsimran Singh il 18 Mar 2022
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.
Benjamin Kraus
Benjamin Kraus il 21 Mar 2022
Modificato: Benjamin Kraus il 21 Mar 2022
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.

Accedi per commentare.

Più risposte (1)

Peter Perkins
Peter Perkins il 14 Mar 2022
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 Commento
Harsimran Singh
Harsimran Singh il 14 Mar 2022
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.

Accedi per commentare.

Prodotti


Release

R2021b

Community Treasure Hunt

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

Start Hunting!

Translated by