Come ignorare date vuote (fine settimana) in un grafico Matplotlib Python finanziaria?
-
13-09-2019 - |
Domanda
ax.plot_date((dates, dates), (highs, lows), '-')
Attualmente sto usando questo comando per tracciare alti e bassi finanziari che utilizzano Matplotlib . E le grandi opere, ma come faccio a rimuovere gli spazi vuoti nella asse x data da giorni senza dati di mercato, come i fine settimana e festivi?
Ho liste di date, alti, bassi, si chiude e si apre. Non riesco a trovare alcun esempio di creazione di un grafico con un asse x che mostrano le date, ma non far rispettare una scala costante.
Soluzione
Credo che hai bisogno di "artificialmente sintetizzare" la forma esatta del lotto desiderato utilizzando xticks
per impostare le etichette delle tacche alle stringhe che rappresentano le date (ovviamente mettendo le zecche a intervalli equidistanti, anche se le date che stai rappresentano non sono equidistanti) e poi con un plot
pianura.
Altri suggerimenti
C'è un esempio di come fare questo sul sito Matplotlib:
https://matplotlib.org/gallery/ticks_and_spines/date_index_formatter.html
Io di solito utilizzare NumPy s ' NaN (non un numero) per i valori che sono non valida o non presente. Sono rappresentati da Matplotlib come lacune nella trama e NumPy fa parte della 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()
Una delle caratteristiche pubblicizzate di scikits.timeseries è "Creare grafici di serie temporali con le etichette degli assi in modo intelligente distanziati ".
È possibile vedere alcuni esempi di trame qui . Nel primo esempio (illustrato di seguito) la frequenza 'business' è usato per i dati, che esclude automaticamente le vacanze e weekend e simili. E 'anche maschere mancanti punti di dati, che si vede come le lacune in questa trama, piuttosto che l'interpolazione lineare.
Fino ad oggi la risposta (2018) con Matplotlib 2.1.2, Python 2.7.12
La equidate_ax
funzione gestisce tutto il necessario per una data semplice asse x con una spaziatura equidistante di punti di dati. Realizzato con ticker.FuncFormatter
sulla base di questo esempio .
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)
Mi sono imbattuto in questo problema ancora una volta ed è stato in grado di creare una funzione decente per gestire questo problema, soprattutto per quanto riguarda datetimes intraday. Credito al @Primer questa risposta.
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()
funzionalità scikits.timeseries è stato in gran parte trasferito a panda, in modo da ora è possibile ricampionare un dataframe per includere solo i valori nei giorni feriali.
>>>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
e poi per tracciare la dataframe come normale
s.resample('B', label='right', closed='right').last().plot()
plt.show()