'plotting error bar on x-axis on a timeseries python
I have data representing mean concentrations over 5 months, some means are over a 24 h period and some are weekly means. I want to plot everything as a scatterplot with time on the x-axis and use some sort of bar (error bar?) to depict the different means correlating time periods, I am able to do this if I use a numerical x-axis but when using a time-date x-axis, I get the following error:
TypeError: unsupported operand type(s) for +: 'Timestamp' and 'float'
I have provided my code and some simple data, but in reality, I have data gaps and different time intervals. My question is, can I do this but representing date-time on my x-aixs? Or is there a better way of achiving this?
Thanks!
Here is some dummy data:
times = [1,2,3,4,5,6,7,8,9]
concentration = [3,6,0,1,3,3,3,3,3]
moves = [0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5]
The code that works can be found below:
fig = plt.figure(figsize=(12,9),dpi=144)
ax = fig.add_subplot(111)
ax.scatter(times, concentration, alpha=0.4)
plt.errorbar(times, concentration,xerr=moves, fmt="o")
plt.yscale('symlog')
plt.show()
Solution 1:[1]
matplotlib is plotting everything against the x axis, including the error bars. It needs to know how to draw the lines. So, if the x axis is of a datetime-like type, the errors should be of a compatible type, and floats are not.
To make it work you should use other types in the moves list, like for example pd.Timedelta:
import matplotlib.pyplot as plt
import pandas as pd
# Datetimes in the x axis, a point every 3 weeks.
times = pd.date_range(start='2022-06-01T00:00:00', freq='3W', periods=9)
concentration = [3,6,0,1,3,3,3,3,3]
# Time intervals to plot as errorbar (here in weeks).
time_intervals = [1, 0.8, 1.5, 1, 1, 2, 1, 0.9, 1.5]
# Compatible types for error bars.
moves = [pd.Timedelta(weeks=w/2) for w in time_intervals]
fig = plt.figure(figsize=(12,9),dpi=144)
ax = fig.add_subplot(111)
ax.scatter(times, concentration, alpha=0.4)
plt.errorbar(times, concentration, xerr=moves, fmt="o")
plt.yscale('symlog')
plt.show()
Result:
Here, I put all the time interval lengths in weeks. pd.Timedelta also supports other parameters, like hours, days, etc. See the documentation for more help.
Since if you subtract two datetimes you get a Timedelta, you could even specify your time intervals like this:
time_intervals = [(pd.to_datetime('2022-06-05T00:00:00') - pd.to_datetime('2022-06-01T00:00:00')),
(pd.to_datetime('2022-06-21T00:00:00') - pd.to_datetime('2022-06-01T00:00:00'))]
#...
print(time_intervals)
[Timedelta('4 days 00:00:00'), Timedelta('20 days 00:00:00')]
So you can get the correct error bars by just subtracting the start date from the end date.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |

