[英]Plotting time data with different frequencies (matplotlib, pandas)
I am trying to combine a Pandas time series and a number of vertical segments (markers) in the same plot. 我正在尝试在同一图中将熊猫时间序列和许多垂直线段(标记)结合起来。 The series has the frequency of 'Q-DEC' (quarter), which in this example is inferred from the dates, but in the real problem is a part of the dataset.
该序列的频率为“ Q-DEC”(四分之一),在本示例中是从日期推断的,但实际上,问题是数据集的一部分。 The markers in general are not aligned with the series and may appear anywhere, not necessarily at the end of a quarter.
标记通常与系列不符,可能会出现在任何位置,而不一定出现在四分之一结束时。
My problem is that if I first plot the series and then the markers, the markers' positions are rounded up to the next end of the quarter (the upper plot). 我的问题是,如果我先绘制序列,然后绘制标记,则标记的位置将四舍五入到该季度的下一个端点(上方的图)。 If I plot the markers first, followed by the series, the markers are in the right positions but the x ticks labels are inappropriate (the lower plot).
如果我先绘制标记,然后再绘制系列,则标记位于正确的位置,但x刻度标签不合适(下图)。
Q : How can I plot the markers at the right positions over a time series plot? 问 :如何在时间序列图上的正确位置绘制标记?
import datetime
import pandas as pd
from pandas import Timestamp
import matplotlib.pyplot as plt
data = pd.DataFrame({0: {Timestamp('2017-03-31'): 1,
Timestamp('2017-06-30'): 2,
Timestamp('2017-09-30'): 3,
Timestamp('2017-12-31'): 3,
Timestamp('2018-03-31'): 2,
Timestamp('2018-06-30'): 1}})
ax = plt.subplot(2,1,1)
data[0].plot(ax=ax,style="-mo")
ax.axvline(pd.Timestamp(datetime.date(2017, 7, 1)), c='r')
ax.axvline(pd.Timestamp(datetime.date(2017, 8, 10)), c='g')
ax.axvline(pd.Timestamp(datetime.date(2017, 9, 20)), c='b')
ax.axvline(pd.Timestamp(datetime.date(2017, 11, 30)), c='k')
ax = plt.subplot(2,1,2)
ax.axvline(pd.Timestamp(datetime.date(2017, 7, 1)), c='r')
ax.axvline(pd.Timestamp(datetime.date(2017, 8, 10)), c='g')
ax.axvline(pd.Timestamp(datetime.date(2017, 9, 20)), c='b')
ax.axvline(pd.Timestamp(datetime.date(2017, 11, 30)), c='k')
data[0].plot(ax=ax,style="-mo")
plt.show()
If you move the dates into the index as a PeriodIndex
, start with freq="M"
to ensure the lines get drawn correctly. 如果将日期作为
PeriodIndex
移入索引,则以freq="M"
开头以确保正确绘制线条。
Then replace the ticks with the index values set to freq="Q-DEC"
. 然后将刻度线替换为设置为
freq="Q-DEC"
的索引值。
data.set_index(pd.PeriodIndex(data.index, freq="M"), inplace=True)
ax = data[0].plot(style="-mo")
ax.axvline(pd.Timestamp(datetime.date(2017, 7, 1)), c='r')
ax.axvline(pd.Timestamp(datetime.date(2017, 8, 10)), c='g')
ax.axvline(pd.Timestamp(datetime.date(2017, 9, 20)), c='b')
ax.axvline(pd.Timestamp(datetime.date(2017, 11, 30)), c='k')
Now reset the ticks: 现在重置刻度线:
q_ticks = data.index.asfreq("Q-DEC")
ax.minorticks_off()
ax.set_xticks(q_ticks)
ax.set_xticklabels(q_ticks)
Output: 输出:
Note: If you don't remove the minor ticks with minorticks_off()
, you'll get some overlap with the original monthly ticks and the new quarterly ticks. 注意:如果不使用
minorticks_off()
删除次要minorticks_off()
,则会与原始的每月价格变动和新的季度价格变动重叠。
Update 更新
If you really need to get the format exactly as it is in your example, you'll need to do a bit of maneuvering with major and minor tick locations and formats: 如果确实需要完全按照示例中的方式获取格式,则需要对主要和次要刻度位置和格式进行一些调整:
ax.get_xaxis().set_tick_params(which='major', pad=15)
q_ticks = data.index.asfreq("Q-DEC")
# extract only the year, and only the year's first listing
major_ticklabels = pd.Series(q_ticks.strftime("%Y"))
major_ticklabels[major_ticklabels.duplicated()] = ""
ax.set_xticks(q_ticks)
ax.set_xticklabels(major_ticklabels)
# format as Q[quarter number]
minor_ticklabels = q_ticks.strftime("Q%q")
ax.xaxis.set_ticks(q_ticks, minor=True)
ax.xaxis.set_ticklabels(minor_ticklabels, minor=True)
The following code can change your second subplot axis like the first subplot. 以下代码可以像第一个子图一样更改第二个子图轴。 Try it if you want the quarter as x-axis.
如果要将四分之一作为x轴,请尝试一下。
data = pd.DataFrame({0: {Timestamp('2017-03-31'): 1,
Timestamp('2017-06-30'): 2,
Timestamp('2017-09-30'): 3,
Timestamp('2017-12-31'): 3,
Timestamp('2018-03-31'): 2,
Timestamp('2018-06-30'): 1}})
xaxis = ['Q{}'.format((pd.to_datetime(date).month-1)//3+1) for date in data.index.values]
plt.xticks(data.index.values,xaxis)
plt.axvline(pd.Timestamp(datetime.date(2017, 7, 1)), c='r')
plt.axvline(pd.Timestamp(datetime.date(2017, 8, 10)), c='g')
plt.axvline(pd.Timestamp(datetime.date(2017, 9, 20)), c='b')
plt.axvline(pd.Timestamp(datetime.date(2017, 11, 30)), c='k')
data[0].plot(style="-mo")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.