首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Matplotlib:当用日期时间轴绘图时,如何跳过一个小时的范围?

Matplotlib:当用日期时间轴绘图时,如何跳过一个小时的范围?
EN

Stack Overflow用户
提问于 2018-01-14 13:27:23
回答 2查看 2.5K关注 0票数 8

我有一种金融工具的逐滴答数据,我正试图用matplotlib绘制这些数据。我正在使用pandas,数据是用DatetimeIndex索引的。

问题是,当我试图绘制多个交易日时,我不能跳过从收盘时间到第二天开盘的时间范围(见示例),当然,我对此不感兴趣。

有没有办法让matplotlib忽略这一点,把结尾的引语和第二天的开场白“粘在一起”呢?我试着通过一个自定义的时间范围:

代码语言:javascript
复制
plt.xticks(time_range)

但结果是一样的。有什么办法吗?

代码语言:javascript
复制
# Example data
instrument = pd.DataFrame(data={
    'Datetime': [
        dt.datetime.strptime('2018-01-11 11:00:11', '%Y-%m-%d %H:%M:%S'),
        dt.datetime.strptime('2018-01-11 13:02:17', '%Y-%m-%d %H:%M:%S'),
        dt.datetime.strptime('2018-01-11 16:59:14', '%Y-%m-%d %H:%M:%S'),

        dt.datetime.strptime('2018-01-12 11:00:11', '%Y-%m-%d %H:%M:%S'),
        dt.datetime.strptime('2018-01-12 13:15:24', '%Y-%m-%d %H:%M:%S'),
        dt.datetime.strptime('2018-01-12 16:58:43', '%Y-%m-%d %H:%M:%S')
    ],
    'Price': [127.6, 128.1, 127.95, 129.85, 129.7, 131.2],
    'Volume': [725, 146, 48, 650, 75, 160]
}).set_index('Datetime')

plt.figure(figsize=(10,5))
top = plt.subplot2grid((4,4), (0, 0), rowspan=3, colspan=4)
bottom = plt.subplot2grid((4,4), (3,0), rowspan=1, colspan=4)
top.plot(instrument.index, instrument['Price'])
bottom.bar(instrument.index, instrument['Volume'], 0.005) 

top.xaxis.get_major_ticks()
top.axes.get_xaxis().set_visible(False)
top.set_title('Example')
top.set_ylabel('Price')
bottom.set_ylabel('Volume')

EN

回答 2

Stack Overflow用户

发布于 2021-01-21 22:10:37

TL;博士

替换matplotlib绘图函数:

代码语言:javascript
复制
top.plot(instrument.index, instrument['Price'])
bottom.bar(instrument.index, instrument['Volume'], 0.005)

对于这些人:

代码语言:javascript
复制
top.plot(range(instrument.index.size), instrument['Price'])
bottom.bar(range(instrument.index.size), instrument['Volume'], width=1)

或者使用这些熊猫绘图功能(只有x轴限制看起来不同):

代码语言:javascript
复制
instrument['Price'].plot(use_index=False, ax=top)
instrument['Volume'].plot.bar(width=1, ax=bottom)

通过与sharex=True共享x轴来对齐这两幅图,并使用dataframe索引设置滴答,如下面的示例所示。

让我首先创建一个示例数据集,并展示如果我使用matplotlib绘图函数绘制它的样子,就像在示例中使用DatetimeIndex作为x变量一样。

创建示例数据集

示例数据是使用历法包创建的,以创建一个实际的DatetimeIndex,其频率为一分钟一分钟,跨越几个工作日和一个周末。

代码语言:javascript
复制
import numpy as np                        # v 1.19.2
import pandas as pd                       # v 1.1.3
import matplotlib.pyplot as plt           # v 3.3.2
import matplotlib.ticker as ticker
import pandas_market_calendars as mcal    # v 1.6.1

# Create datetime index with a 'minute start' frequency based on the New
# York Stock Exchange trading hours (end date is inclusive)
nyse = mcal.get_calendar('NYSE')
nyse_schedule = nyse.schedule(start_date='2021-01-07', end_date='2021-01-11')
nyse_dti = mcal.date_range(nyse_schedule, frequency='1min', closed='left')\
               .tz_convert(nyse.tz.zone)
# Remove timestamps of closing times to create a 'period start' datetime index
nyse_dti = nyse_dti.delete(nyse_dti.indexer_at_time('16:00'))

# Create sample of random data consisting of opening price and
# volume of financial instrument traded for each period
rng = np.random.default_rng(seed=1234)  # random number generator
price_change = rng.normal(scale=0.1, size=nyse_dti.size)
price_open = 127.5 + np.cumsum(price_change)
volume = rng.integers(100, 10000, size=nyse_dti.size)
df = pd.DataFrame(data=dict(Price=price_open, Volume=volume), index=nyse_dti)
代码语言:javascript
复制
df.head()

#                             Price       Volume
#  2021-01-07 09:30:00-05:00  127.339616  7476
#  2021-01-07 09:31:00-05:00  127.346026  3633
#  2021-01-07 09:32:00-05:00  127.420115  1339
#  2021-01-07 09:33:00-05:00  127.435377  3750
#  2021-01-07 09:34:00-05:00  127.521752  7354

使用matplotlib使用 DatetimeIndex绘制数据

这个示例数据现在可以使用matplotlib绘图函数来绘制,就像在您的示例中一样,但是请注意,子图是通过使用plt.subplotssharex=True参数创建的。这将使该行与条形图正确地对齐,并使使用matplotlib的交互式接口与两个子图都成为可能。

代码语言:javascript
复制
# Create figure and plots using matplotlib functions
fig, (top, bot) = plt.subplots(2, 1, sharex=True, figsize=(10,5),
                               gridspec_kw=dict(height_ratios=[0.75,0.25]))
top.plot(df.index, df['Price'])
bot.bar(df.index, df['Volume'], 0.0008)

# Set title and labels
top.set_title('Matplotlib plots with unwanted gaps', pad=20, size=14, weight='semibold')
top.set_ylabel('Price', labelpad=10)
bot.set_ylabel('Volume', labelpad=10);

使用无间隙的matplotlib通过使用一系列整数绘制数据

这些空白的问题可以通过简单地忽略DatetimeIndex和使用一系列整数来解决。因此,大部分工作都是在创建适当的勾标。下面是一个示例:

代码语言:javascript
复制
# Create figure and matplotlib plots with some additional formatting
fig, (top, bot) = plt.subplots(2, 1, sharex=True, figsize=(10,5),
                               gridspec_kw=dict(height_ratios=[0.75,0.25]))
top.plot(range(df.index.size), df['Price'])
top.set_title('Matplotlib plots without any gaps', pad=20, size=14, weight='semibold')
top.set_ylabel('Price', labelpad=10)
top.grid(axis='x', alpha=0.3)
bot.bar(range(df.index.size), df['Volume'], width=1)
bot.set_ylabel('Volume', labelpad=10)

# Set fixed major and minor tick locations
ticks_date = df.index.indexer_at_time('09:30')
ticks_time = np.arange(df.index.size)[df.index.minute == 0][::2] # step in hours
bot.set_xticks(ticks_date)
bot.set_xticks(ticks_time, minor=True)

# Format major and minor tick labels
labels_date = [maj_tick.strftime('\n%d-%b').replace('\n0', '\n')
               for maj_tick in df.index[ticks_date]]
labels_time = [min_tick.strftime('%I %p').lstrip('0').lower()
               for min_tick in df.index[ticks_time]]
bot.set_xticklabels(labels_date)
bot.set_xticklabels(labels_time, minor=True)
bot.figure.autofmt_xdate(rotation=0, ha='center', which='both')

为交互式情节创建动态刻度

如果您喜欢使用matplotlib的交互接口(使用pan/缩放),则需要使用来自matplotlib滴答器模块的定位器和格式化器。下面是一个如何设置滴答的例子,其中主要的滴答是固定的,格式和上面一样,但是当你放大/退出情节时,小滴答会自动生成:

代码语言:javascript
复制
# Set fixed major tick locations and automatic minor tick locations
ticks_date = df.index.indexer_at_time('09:30')
bot.set_xticks(ticks_date)
bot.xaxis.set_minor_locator(ticker.AutoLocator())

# Format major tick labels
labels_date = [maj_tick.strftime('\n%d-%b').replace('\n0', '\n')
               for maj_tick in df.index[ticks_date]]
bot.set_xticklabels(labels_date)

# Format minor tick labels
def min_label(x, pos):
    if 0 <= x < df.index.size:
        return df.index[int(x)].strftime('%H:%M')
min_fmtr = ticker.FuncFormatter(min_label)
bot.xaxis.set_minor_formatter(min_fmtr)

bot.figure.autofmt_xdate(rotation=0, ha='center', which='both')

文档:替代解决方案的示例日期时间字符串格式代码

票数 4
EN

Stack Overflow用户

发布于 2021-10-18 22:29:50

也许使用https://pypi.org/project/mplfinance/

允许模仿你在大多数服务中看到的通常的财务计划。

当您调用mplfinance mpf.plot()函数时,有一个kwarg show_nontrading,默认情况下它被设置为False,这样就不会自动绘制这些不需要的空白。(若要绘制它们,请设置show_nontrading=True)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48250054

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档