ax.plot_date((dates, dates), (highs, lows), '-')
我目前正在使用此命令使用Matplotlib绘制财务高点和低点。效果很好,但是如何去除没有市场数据的天数(例如周末和节假日)在 x 轴上留下的空白?
我有日期、高点、低点、收盘价和开盘价的列表。我找不到任何使用 x 轴创建图表的示例,该图表显示日期但不强制执行恒定比例。
ax.plot_date((dates, dates), (highs, lows), '-')
我目前正在使用此命令使用Matplotlib绘制财务高点和低点。效果很好,但是如何去除没有市场数据的天数(例如周末和节假日)在 x 轴上留下的空白?
我有日期、高点、低点、收盘价和开盘价的列表。我找不到任何使用 x 轴创建图表的示例,该图表显示日期但不强制执行恒定比例。
scikits.timeseries的广告功能之一是“创建具有智能间隔轴标签的时间序列图”。
您可以在此处查看一些示例图。在第一个示例(如下所示)中,“业务”频率用于数据,自动排除节假日和周末等。它还掩盖了缺失的数据点,您在此图中将其视为间隙,而不是对其进行线性插值。
我认为您需要通过xticks
将刻度标签设置为代表日期的字符串来“人工合成”您想要的确切形式的绘图(当然,即使您所代表的日期不是等距的,也将刻度放置在等距的间隔) 然后使用普通的plot
.
对于无效或不存在的值,我通常会使用NumPy的 NaN(不是数字)。它们由 Matplotlib 表示为图中的间隙,NumPy 是 pylab/Matplotlib 的一部分。
>>> import pylab
>>> xs = pylab.arange(10.) + 733632. # valid date range
>>> ys = [1,2,3,2,pylab.nan,2,3,2,5,2.4] # some data (one undefined)
>>> pylab.plot_date(xs, ys, ydate=False, linestyle='-', marker='')
[<matplotlib.lines.Line2D instance at 0x0378D418>]
>>> pylab.show()
Matplotlib 2.1.2、Python 2.7.12 的最新答案(2018 年)
该函数可以equidate_ax
处理数据点间距等距的简单日期 x 轴所需的一切。用ticker.FuncFormatter
基于这个例子来实现。
from __future__ import division
from matplotlib import pyplot as plt
from matplotlib.ticker import FuncFormatter
import numpy as np
import datetime
def equidate_ax(fig, ax, dates, fmt="%Y-%m-%d", label="Date"):
"""
Sets all relevant parameters for an equidistant date-x-axis.
Tick Locators are not affected (set automatically)
Args:
fig: pyplot.figure instance
ax: pyplot.axis instance (target axis)
dates: iterable of datetime.date or datetime.datetime instances
fmt: Display format of dates
label: x-axis label
Returns:
None
"""
N = len(dates)
def format_date(index, pos):
index = np.clip(int(index + 0.5), 0, N - 1)
return dates[index].strftime(fmt)
ax.xaxis.set_major_formatter(FuncFormatter(format_date))
ax.set_xlabel(label)
fig.autofmt_xdate()
#
# Some test data (with python dates)
#
dates = [datetime.datetime(year, month, day) for year, month, day in [
(2018,2,1), (2018,2,2), (2018,2,5), (2018,2,6), (2018,2,7), (2018,2,28)
]]
y = np.arange(6)
# Create plots. Left plot is default with a gap
fig, [ax1, ax2] = plt.subplots(1, 2)
ax1.plot(dates, y, 'o-')
ax1.set_title("Default")
ax1.set_xlabel("Date")
# Right plot will show equidistant series
# x-axis must be the indices of your dates-list
x = np.arange(len(dates))
ax2.plot(x, y, 'o-')
ax2.set_title("Equidistant Placement")
equidate_ax(fig, ax2, dates)
我再次遇到了这个问题,并且能够创建一个体面的函数来处理这个问题,尤其是关于日内日期时间。感谢@Primer这个答案。
def plot_ts(ts, step=5, figsize=(10,7), title=''):
"""
plot timeseries ignoring date gaps
Params
------
ts : pd.DataFrame or pd.Series
step : int, display interval for ticks
figsize : tuple, figure size
title: str
"""
fig, ax = plt.subplots(figsize=figsize)
ax.plot(range(ts.dropna().shape[0]), ts.dropna())
ax.set_title(title)
ax.set_xticks(np.arange(len(ts.dropna())))
ax.set_xticklabels(ts.dropna().index.tolist());
# tick visibility, can be slow for 200,000+ ticks
xticklabels = ax.get_xticklabels() # generate list once to speed up function
for i, label in enumerate(xticklabels):
if not i%step==0:
label.set_visible(False)
fig.autofmt_xdate()
scikits.timeseries
功能已在很大程度上移至 pandas,因此您现在可以重新采样数据框以仅包含工作日的值。
>>>import pandas as pd
>>>import matplotlib.pyplot as plt
>>>s = pd.Series(list(range(10)), pd.date_range('2015-09-01','2015-09-10'))
>>>s
2015-09-01 0
2015-09-02 1
2015-09-03 2
2015-09-04 3
2015-09-05 4
2015-09-06 5
2015-09-07 6
2015-09-08 7
2015-09-09 8
2015-09-10 9
>>> s.resample('B', label='right', closed='right').last()
2015-09-01 0
2015-09-02 1
2015-09-03 2
2015-09-04 3
2015-09-07 6
2015-09-08 7
2015-09-09 8
2015-09-10 9
然后正常绘制数据框
s.resample('B', label='right', closed='right').last().plot()
plt.show()
您可以简单地将日期更改为字符串:
import matplotlib.pyplot as plt
import datetime
f = plt.figure(1, figsize=(10,5))
ax = f.add_subplot(111)
today = datetime.datetime.today().date()
yesterday = today - datetime.timedelta(days=1)
three_days_later = today + datetime.timedelta(days=3)
x_values = [yesterday, today, three_days_later]
y_values = [75, 80, 90]
x_values = [f'{x:%Y-%m-%d}' for x in x_values]
ax.bar(x_values, y_values, color='green')
plt.show()