英文:
Adding a circle on specific date in a matplotlib plot
问题
我使用以下代码创建了一个matplotlib绘图:
ax.plot(df_c.index, y1, color='b')
这里的df_c.index
是一个DatetimeIndex
:
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)
上述代码创建了一个线图。
我想在日期'2020-04-12'
上添加一个值为100
的圆圈。我尝试了以下代码:
ax.plot(datetime.date(2020, 04, 12), 100, 'bo')
但它不起作用。我该如何修复它?
英文:
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?
答案1
得分: 4
我不确定您想在哪里绘制您的圆圈,但我在这里提供了三个不同的圆圈位置以及一个更简单的第四个备选项,只是为了突出显示特定日期。演示图像显示在底部。首先,让我们绘制一些数据:
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))] # 一些随机的y值
# 一个要圈起来的任意日期值
encircled_date = dates[1]
val_of_encircled_date = y[1]
# 绘制图表
fig, ax = plt.subplots()
ax.plot_date(dates, y, '-')
bottom, top = plt.ylim() # 后面,我们需要y轴最小值以正确定位圆圈
现在,如果您只想在图表上有一个圆圈,经过您指定的日期,最简单且(在我看来)最好的方法是只需重新绘制该特定值,但使用 markerstyle='o'
。根据您的喜好调整标记大小、线宽和颜色:
# 在特定图表值周围绘制一个圆圈
ax.plot_date(encircled_date, val_of_encircled_date,
'og', # 标记样式 'o',颜色 'g'
fillstyle='none', # 圆圈不填充颜色
ms=10.0) # 标记/圆圈的大小
然后,如果您希望在x轴上的日期刻度周围有一个圆圈,用于指定日期,这会稍微复杂一些,具体取决于您需要圈起的细节。当然,您可以使用上面的方法仅获得刻度周围的小圆圈,但我将展示一种基于另一个SO问题的更高级方法:
# 在x轴上特定日期的‘刻度’周围绘制一个圆圈
circle1 = plt.Circle((encircled_date, bottom), # 位置
1.0 / len(dates), # 半径
color='r',
clip_on=False, # 允许在轴外绘制
fill=False)
ax.add_artist(circle1)
上述解决方案仅包围刻度,而不包括日期标签本身。我们可以微调圆圈以适应日期标签,通过调整两个偏移参数:
# 在x轴上特定日期的标签周围绘制一个圆圈
pos_offset = 0.5
len_offset = 0.4
circle2 = plt.Circle((encircled_date, bottom-pos_offset), # 位置
(1.0+len_offset) / len(dates), # 半径
color='purple',
clip_on=False, # 允许在轴外绘制
fill=False)
ax.add_artist(circle2)
然而,这种微调可能会是一项繁琐的任务。如果您的目标只是强调特定日期,最好的方法可能是简单地重新配置x标签。例如,您可以像这样更改标签的颜色:
ax.get_xticklabels()[2].set_color("red")
ax.get_xticklabels()[2].set_weight("bold")
这四种不同的方法显示在下面的图像中。希望这可以帮助您。
最后一句话: 当您获得一个日期密集的x轴时,可能值得研究更高级的日期标签格式化,您可以在官方文档中详细了解这方面的知识。例如,他们展示了如何将标签巧妙地旋转以使它们更接近而不重叠。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论