Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plot datetime.timedelta using matplotlib and python

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

like image 474
xpress_embedo Avatar asked Jan 17 '18 05:01

xpress_embedo


People also ask

How do I plot time series data in Matplotlib?

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.

What is Timedelta in datetime Python?

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.

Can you plot datetime Python?

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.

Can Matplotlib plot real time graphs in Python?

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.


3 Answers

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))

Example Bar Graph

like image 156
Phil Avatar answered Nov 16 '22 19:11

Phil


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()

enter image description here

like image 41
ImportanceOfBeingErnest Avatar answered Nov 16 '22 19:11

ImportanceOfBeingErnest


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

like image 1
Arvydas Kausas Avatar answered Nov 16 '22 18:11

Arvydas Kausas