I am working on a task, where I need to calculate time spent on each day and then represent that time using a bar plot, so for this task I used python and able to get time spent on each day, and stored it in a list "time_list", now I don't understand how to plot this using matplotlib function. The problem is that, this list contains datetime.timedelta class values. Example:
time_list
[datetime.timedelta(0, 23820), datetime.timedelta(0, 27480), datetime.timedelta(0, 28500), datetime.timedelta(0, 24180), datetime.timedelta(0, 27540), datetime.timedelta(0, 28920), datetime.timedelta(0, 28800), datetime.timedelta(0, 29100), datetime.timedelta(0, 29100), datetime.timedelta(0, 24480), datetime.timedelta(0, 27000)]
And these values meaning is as follow:
Total Time Spent on 2 is 6:37:00
Total Time Spent on 3 is 7:38:00
Total Time Spent on 4 is 7:55:00
Total Time Spent on 5 is 6:43:00
Total Time Spent on 8 is 7:39:00
Total Time Spent on 9 is 8:02:00
Total Time Spent on 10 is 8:00:00
Total Time Spent on 11 is 8:05:00
Total Time Spent on 12 is 8:05:00
Total Time Spent on 15 is 6:48:00
Total Time Spent on 16 is 7:30:00
Can someone help me in plotting this. Thanks in advance
In X-axis we should have a variable of DateTime. In Y-axis we can have the variable which we want to analyze with respect to time. plt. plot() method is used to plot the graph in matplotlib.
A timedelta object represents a duration, the difference between two dates or times. All arguments are optional and default to 0 . Arguments may be integers or floats, and may be positive or negative. Only days, seconds and microseconds are stored internally.
Aside from the built-in Python datetime object, PyGMT supports input using ISO formatted strings, pandas , xarray , as well as numpy . These data types can be used to plot specific points as well as get passed into the region parameter to create a range of the data on an axis.
To create a real-time plot, we need to use the animation module in matplotlib. We set up the figure and axes in the usual way, but we draw directly to the axes, ax , when we want to create a new frame in the animation.
I don't think you can directly plot timedelta
in Matplotlib, but since you already have the number of seconds, you can define a custom tick format that converts seconds to hours and minutes.
from matplotlib.ticker import FuncFormatter
def format_func(x, pos):
hours = int(x//3600)
minutes = int((x%3600)//60)
seconds = int(x%60)
return "{:d}:{:02d}".format(hours, minutes)
# return "{:d}:{:02d}:{:02d}".format(hours, minutes, seconds)
formatter = FuncFormatter(format_func)
Then, you can set the tick formatter for the y-axis.
Here's an example using a bar
.
labels = [2, 3, 4, 5, 8, 9, 10, 11, 12, 15, 16]
seconds = [i.seconds for i in time_list]
f = plt.figure()
ax = f.add_subplot(1,1,1)
ax.bar(labels, seconds)
ax.yaxis.set_major_formatter(formatter)
# this locates y-ticks at the hours
ax.yaxis.set_major_locator(matplotlib.ticker.MultipleLocator(base=3600))
# this ensures each bar has a 'date' label
ax.xaxis.set_major_locator(matplotlib.ticker.MultipleLocator(base=1))
While matplotlib can in principle handle datetime objects, the bar plot cannot interprete them directly. So one may add an arbitrary date to the timedeltas and convert to numbers using matplotlib.dates.date2num()
. Then using a DateFormatter
enables nice ticklabels.
import numpy as np
import datetime
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
days = [2, 3, 4, 5, 8, 9, 10, 11, 12, 15, 16]
time_list = [datetime.timedelta(0, 23820), datetime.timedelta(0, 27480),
datetime.timedelta(0, 28500), datetime.timedelta(0, 24180),
datetime.timedelta(0, 27540), datetime.timedelta(0, 28920),
datetime.timedelta(0, 28800), datetime.timedelta(0, 29100),
datetime.timedelta(0, 29100), datetime.timedelta(0, 24480),
datetime.timedelta(0, 27000)]
# specify a date to use for the times
zero = datetime.datetime(2018,1,1)
time = [zero + t for t in time_list]
# convert datetimes to numbers
zero = mdates.date2num(zero)
time = [t-zero for t in mdates.date2num(time)]
f = plt.figure()
ax = f.add_subplot(1,1,1)
ax.bar(days, time, bottom=zero)
ax.yaxis_date()
ax.yaxis.set_major_formatter(mdates.DateFormatter("%H:%M"))
# add 10% margin on top (since ax.margins seems to not work here)
ylim = ax.get_ylim()
ax.set_ylim(None, ylim[1]+0.1*np.diff(ylim))
plt.show()
I had similar problem when I wanted to plot the data with a y axis
equal to Timedelta64[ns]
type. I found the easiest solution to handle this issue from this blog : solution. For short, just change the dtype
of your column to .astype('timedelta64[m]')
. You can change to hour, minutes or seconds for your case just by changing the value in a square brackets. It changes the dtype of your y
column to float64
and then you can easily plot the bar graph or plot with normal units and not like nanoseconds
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With