3

I have a code which allows me to plot two timeseries of data. I also have a number of events which I plot as a series of vertical lines within the timeseries. I have this timeseries for three years: 2015, 2016, and 2017. My code works well for 2015 and 2016, and I produce a graph like so (this is for 2016):Timeseries data (red and blue) and event data (dotted vertical lines) plotted.

However, when I plot my data for 2017, I cannot reproduce the vertical lines for event data, as shown below (it's hard to see, but in this graph there are no vertical dashed lines as there were in first one):

Timeseries data (red and blue) but no event data plotted.

Any ideas as to why my code does not work for 2017? The data are stored in .csv files, and event data is plotted from a column of data in the .csv file that I have converted into a series of datetime objects. I have checked, and the formats for the 2015, 2016 and 2017 .csv files remain the same.

FYI, here is the code that I have used to plot:

#Change format of "dates" column from string to datetime object    
FMT = '%d/%m/%Y'
dtlist = []
for i in range(0, len(dates)):
    dtlist.append(datetime.datetime.strptime(dates[i], FMT))  


##EVENT:
#Remove all values where there is no event
df2 = df_17[pd.notnull(df_17['event'])]

#Convert event values to datetime objects
df2['event'] = pd.to_datetime(df2['event'], format="%d/%m/%Y")
event_list = df2['event'].tolist()

#Plot timeseries on graph
fig, ax1 = plt.subplots(figsize=(18, 6))
plt.plot(dtlist, series_1, color='b', label='Series 1')
ymin, ymax = ax1.get_ylim()
for value in event_list:
    plt.axvline(x=value, ymin=ymin, ymax=ymax-1, color='k', linewidth=1.0, linestyle='--')    
ax1.set_xlabel('Time')
ax1.set_ylabel('Series 1')

ax2=ax1.twinx()
ax2.plot(dtlist, series_2, color='r', label='Series_2')
ax2.set_ylabel('Series 2')

plt.legend
plt.show()

Any help much appreciated!

ailsa_naismith
  • 333
  • 2
  • 4
  • 15
  • What is the value of `event_list`? Are there dates after `2017-01-01`? – unutbu Jul 31 '17 at 14:47
  • Have you tested that `ymin` and `ymax` are reasonable values? From the documentation, they must each be between 0 and 1 to be able to plot the vertical lines. `ymax=ymax-1` seems like it could be a little suspicious. – marcushobson Jul 31 '17 at 14:58
  • `event_list` is a list of values from a dataframe column: it has six values in it, corresponding to events in 2017. There are dates after `2017-01-01`, for instance my first event is `2017-01-25`. – ailsa_naismith Jul 31 '17 at 15:01
  • I think that `ymin` and `ymax` are reasonable. I have the line `ymin, ymax = ax1.get_ylim()` just prior to plotting `axvline`, so I assume that `ymin ` and `ymax ` correspond to the y-values for `ax1 `, which are 0 and 6000, respectively. – ailsa_naismith Jul 31 '17 at 15:04
  • I got the idea for `ymax = ymax-1` from this post: [link](https://stackoverflow.com/questions/21488085/pandas-graphing-a-timeseries-with-vertical-lines-at-selected-dates), which I think is a good one. Using `ymax = ymax` does not change my output. – ailsa_naismith Jul 31 '17 at 15:06
  • Looking at the plots I doubt that both plots are produced by the same code. Hence it's really hard for us to guess what you have changed in between. Note that questions such as this one should always include a [mcve]. – ImportanceOfBeingErnest Jul 31 '17 at 17:19
  • Try not using `ymax` and `ymin` at all. – Warren Weckesser Jul 31 '17 at 17:41
  • The plots are produced by the same code, but I should specify that I have changed the length of the graph for 2017, to reflect the fact that I only have data until July. The only other difference, I think, is the presence in 2017 graph of horizontal/vertical gridlines. – ailsa_naismith Aug 01 '17 at 10:25

2 Answers2

6

In a comment, you say you got the idea for your values for ymin and ymax from Pandas graphing a timeseries, with vertical lines at selected dates, but the example there uses vlines, not axvline. vlines uses the data scale. axvline expects values between 0 and 1 for ymin and ymax. That is, the y values are specified in fractions (between 0 and 1) of the y-axis. If you specify, say, ymin=0 and ymax=0.5, you will get a vertical line that goes from the bottom of the axis to the middle of the axis, regardless of the current data scale of the plot. If you zoom in or out, or pan up or down, the half-height vertical line remains.

The default values for ymin and ymax are 0 and 1, respectively, so to get a line that goes from the bottom to the top, you could simply leave out the arguments.

Try this:

    plt.axvline(x=value, color='k', linewidth=1.0, linestyle='--') 
Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214
0

Many thanks to all who contributed. Warren Weckesser gave the correct solution: using axvline understands that ymin and ymax are determined in fractions between 0 and 1 of the y-axis. Removing them, and using this line instead:

plt.axvline(x=value, color='k', linewidth=1.0, linestyle='--') 

solved the issue. My output graph:2017 Events plotted.

Cheers!

Community
  • 1
  • 1
ailsa_naismith
  • 333
  • 2
  • 4
  • 15