كيفية تخطي التواريخ الفارغة (عطلات نهاية الأسبوع) في الرسم البياني matplotlib python مالي؟
-
13-09-2019 - |
سؤال
ax.plot_date((dates, dates), (highs, lows), '-')
أنا حاليا باستخدام هذا الأمر لرسم الارتفاعات المالية والاداءات باستخدام matplotlib.. وبعد إنه يعمل بشكل رائع، ولكن كيف يمكنني إزالة المساحات الفارغة في المحور X الذي تركت منذ أيام دون بيانات السوق، مثل عطلات نهاية الأسبوع والأعياد؟
لدي قوائم بالتواريخ والارواف والأقصاد والإغلاق والفتح. لا يمكنني العثور على أي أمثلة على إنشاء رسم بياني مع محور X الذي يظهر التواريخ ولكن لا يفرض مقياس ثابت.
المحلول
أعتقد أنك بحاجة إلى "توليف مصطنع" الشكل الدقيق للمصورة التي تريدها باستخدام xticks
لتعيين ملصقات التجزئة على الأوتار التي تمثل التواريخ (بالطبع وضع القراد على فترات متساوية على الرغم من أن التواريخ التي تمثلها ليست متساوية) ثم باستخدام سهل plot
.
نصائح أخرى
هناك مثال على كيفية القيام بذلك على موقع Matplotlib:
https://mplotlib.org/gallery/ticks_and_spines/date_index_formatter.html.
سأستمر عادة numpy.نان (وليس عددا) للقيم غير الصحيحة أو غير موجودة. يمثلونها matplotlib حيث أن الفجوات في المؤامرة والحنمة هي جزء من 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()
واحدة من الميزات المعلن عنها scikits.timeseries. "إنشاء مؤامرات سلسلة الوقت مع تسميات المحور متباعدة بذكاء".
يمكنك أن ترى بعض الأمثلة هنا. وبعد في المثال الأول (الموضح أدناه) يستخدم تردد "الأعمال" للبيانات، مما يستبعد تلقائيا العطل وعطلات نهاية الأسبوع وما شابه ذلك. كما أنه أقنع نقاط البيانات المفقودة، والتي تراها ثغرات في هذه المؤامرة، بدلا من الاستراءة الخطي لهم.
إجابة محدثة (2018) مع Matplotlib 2.1.2، بيثون 2.7.12
الوظيفة equidate_ax
يعالج كل ما تحتاجه لتاريخ X-Axis بسيطة مع تباعد متساوي نقاط نقاط البيانات. أدركت مع 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 إلى الباندا إلى حد كبير، حتى تتمكن الآن من إعادة تشكيل إطارا بيانات لا تتضمن فقط القيم في أيام الأسبوع.
>>>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
ثم قم بمصنع الإطار Data
s.resample('B', label='right', closed='right').last().plot()
plt.show()