Comment ignorer les dates vides (week-end) dans un graphique financier Matplotlib Python?
-
13-09-2019 - |
Question
ax.plot_date((dates, dates), (highs, lows), '-')
J'utilise actuellement cette commande pour tracer des hauts et des bas financiers en utilisant Matplotlib . Il fonctionne très bien, mais comment puis-je supprimer les espaces vides dans l'axe des x gauche par jour sans données sur le marché, comme les week-ends et les jours fériés?
Je liste des dates, des hauts, des bas, se ferme et ouvre. Je ne trouve aucun exemple de créer un graphique avec un axe x qui montrent les dates, mais ne l'applique pas à une échelle constante.
La solution
Je pense que vous avez besoin de « synthétiser artificiellement » la forme exacte de la parcelle que vous voulez en utilisant xticks
pour définir les étiquettes de tiques aux chaînes représentant les dates (de placer bien sûr les tiques à intervalles équidistants, même si les dates que vous représentez ne sont pas équidistants), puis en utilisant une plot
plaine.
Autres conseils
Il y a un exemple de la façon de le faire sur le site Matplotlib:
https://matplotlib.org/gallery/ticks_and_spines/date_index_formatter.html
Je généralement utiliser NumPy NAN (pas un nombre) s pour les valeurs qui sont invalide ou non présent. Ils sont représentés par Matplotlib comme des lacunes dans l'intrigue et NumPy fait partie de 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()
L'une des caractéristiques de scikits.timeseries est « créer des tracés de séries chronologiques avec des étiquettes d'axe intelligemment espacés ».
Vous pouvez voir quelques exemples de parcelles . Dans le premier exemple (illustré ci-dessous) la fréquence « d'affaires » est utilisé pour les données, ce qui exclut automatiquement les jours fériés et les week-ends et autres. Il a également des masques manquants de données, que vous voyez que les lacunes dans ce complot, plutôt que de façon linéaire les interpoler.
Jusqu'à ce jour de réponse (2018) avec Matplotlib 2.1.2, Python 2.7.12
Les poignées equidate_ax
fonction tout ce dont vous avez besoin pour une simple date axe x avec un espacement à égale distance des points de données. Réalisé avec ticker.FuncFormatter
basé sur cet exemple .
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)
Je suis tombé sur ce problème nouveau et a été en mesure de créer une fonction décente pour gérer ce problème, en particulier en ce qui concerne datetimes intraday. Crédit @Primer pour cette réponse.
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()
fonctionnalité scikits.timeseries a largement été déplacé vers pandas géants, de sorte que vous pouvez rééchantillonner une trame de données à inclure uniquement les valeurs en semaine.
>>>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
et de tracer le dataframe comme normal
s.resample('B', label='right', closed='right').last().plot()
plt.show()