1

I have a matpltolib plot made using this code:

ax.plot(df_c.index, y1, color='b')

Here df_c.index is:

DatetimeIndex(['2019-10-31', '2019-11-01', '2019-11-02', '2019-11-03',
               '2019-11-04', '2019-11-05', '2019-11-06', '2019-11-07',
               '2019-11-08', '2019-11-09',
               ...
               '2020-04-04', '2020-04-05', '2020-04-06', '2020-04-07',
               '2020-04-08', '2020-04-09', '2020-04-10', '2020-04-11',
               '2020-04-12', '2020-04-13'],
              dtype='datetime64[ns]', length=166, freq=None)

The above code makes a lineplot.

I want to add a circle on this date '2020-04-12' with a value of 100. How do I do that? I tried:

ax.plot(datetime.date(2020, 04, 12), 100, 'bo')

but it does not work. How can I fix it?

user308827
  • 21,227
  • 87
  • 254
  • 417

1 Answers1

4

I'm not entirely certain where you want to draw your circle, but I present here three different circle positions, and a simpler fourth alternative just for highlighting a specific date. A demo image is shown at the bottom. First, let's just plot some data:

import matplotlib.pyplot as plt

dates = ['2019-10-31', '2019-11-01', '2019-11-02', '2019-11-03']

y = [i*i for i in range(len(dates))] # some random y values

# An arbitrary date value to encircle 
encircled_date = dates[1]
val_of_encircled_date = y[1]

# Plot the graph
fig, ax = plt.subplots()
ax.plot_date(dates,y,'-')
bottom, top = plt.ylim() # Later, we'll need the min value of the y-axis for correct positioning of circle

Now, if you just want a circle at the graph, as it passes through your specific date, the simplest and (imho) best approach is to simply replot that specific value, but with markerstyle='o'. Adjust marker size, line width and color to your preferences:

# Plot a circle around specific graph value
ax.plot_date(encircled_date, val_of_encircled_date,
                'og', # marker style 'o', color 'g'
                fillstyle='none', # circle is not filled (with color)
                ms=10.0) # size of marker/circle

Then, if you instead wanted a circle around the date-tick, on the x-axis for your specific date, it is a little more tricky depending on what details you need to encircle. Of course, you could use the approach above to get a small circle around the tick only, but I'll show a more advanced approach based on another SO-question:

# Plot a circle around the 'tick' of specific date on the x-axis
circle1 = plt.Circle((encircled_date, bottom), # position
                    1.0 / len(dates), # radius
                    color='r',
                    clip_on=False, # allow drawing outside of axes
                    fill=False)
ax.add_artist(circle1)

The above solution only encircles the tick, and not the date label itself. We may micro adjust the circle to fit the date-label inside, by tuning two offset parameters,

# Plot a circle around the specific date's label on the x-axis
pos_offset = 0.5
len_offset = 0.4
circle2 = plt.Circle((encircled_date, bottom-pos_offset), # position
                    (1.0+len_offset) / len(dates), # radius
                    color='purple',
                    clip_on=False, # allow drawing outside of axis
                    fill=False)
ax.add_artist(circle2)

However, this tuning may be a tedious task. If your objective is only to emphasize this particular date, it may be better to simply reconfigure the x-label. You may for instance change the color of the label like this,

ax.get_xticklabels()[2].set_color("red")
ax.get_xticklabels()[2].set_weight("bold")

The four different approaches are shown in the image below. I hope this helps.

One final remark: When you get a densely populated x-axis of dates, it might be worthwhile looking into more advanced formatting of date-labels which you can read all about in the official documentation. For instance, they show how to neatly rotate the labels to fit them closer together without overlapping.

Different approaches to highlighting a plot value

Wololo
  • 1,249
  • 1
  • 13
  • 25
  • thanks @magnus, this is a great start! The x-axis should be a `DatetimeIndex` as I specified and not a list of strings as you assumed. – user308827 Jan 03 '20 at 17:24
  • @user308827, It was intended as a simplification, not an assumption. However, I did assume that you're using `pandas` which is not mentioned or taged in your post. I tried to address the issue of drawing the circle, not the issue of plotting by using dates on the axes. These are, in my opinion, two different questions and might deserve two different posts. If you provide more details and the raw data from which the `DatetimeIndex` is created, I might be able to help you further. – Wololo Jan 06 '20 at 10:50
  • ... According to the [Pandas doc](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DatetimeIndex.html), you might be able to do something similar to: `date_strings=[str(d) for d in df_c.index.date]` to obtain a list of dates strings that I used in my example. – Wololo Jan 06 '20 at 10:50