【问题标题】:Matplotlib improve broken axis in subplotsMatplotlib 改进子图中的断轴
【发布时间】:2022-01-14 06:58:41
【问题描述】:

我想在子图之间创建一个中断,但希望左侧覆盖 80% 的图,右侧覆盖 20% 的图。我也调整了 x 轴以仅覆盖数据,但理想情况下,该图将覆盖相同比例的一部分,以便数据具有相同的拉伸。

另外,有没有办法让 2 个 sublplots 更靠近彼此,中间有一条断线? 包含数据的 .csv 文件可以在here找到。

import numpy as np
import matplotlib.pyplot as plt
from pandas import read_csv
import pandas as pd
import csv
import datetime
import matplotlib.dates as mdates
import matplotlib.gridspec as gridspec
from datetime import datetime
import datetime as dt
import statistics

csv = 'Data.csv'

df = pd.read_csv(csv, header=None, names=['time', 'tide', 'ho', 'tp', 'lo', 'mwd'])
xp = [datetime.strptime(d, "%d/%m/%YT%H:%M") for d in df['time']]

xs = mdates.date2num(xp)
date = mdates.DateFormatter ("%d/%m/%Y\n")

fig = plt.figure(tight_layout=False)
gs = gridspec.GridSpec(4, 2)

#Subplot 1 
ax11 = fig.add_subplot(gs[0, 0])
ax11.xaxis.set_major_formatter(date)
ax11.set_xlim(dt.datetime(2019, 3, 1, 0), dt.datetime(2019, 9, 30, 0))

ax12 = fig.add_subplot(gs[0, 1])
ax12.xaxis.set_major_formatter(date)
ax12.set_xlim(dt.datetime(2020, 8, 1, 0), dt.datetime(2020, 9, 30, 0))

#surveys
ax11.axvline(dt.datetime(2019,3,26,14), color = 'red', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,4,10,14), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,4,11,15), color = 'red', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,5,1,9), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,5,3,10), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,5,10,15), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,5,17,9), color = 'red', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,5,20,12), color = 'red', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,6,6,13), color = 'red', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,6,14,8), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,6,18,12), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,6,21,14), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,6,24,16), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,6,25,6), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,6,25,17), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,7,2,11), color = 'red', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,7,3,11), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,7,4,12), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,7,16,10), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,7,31,10), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,8,1,11), color = 'red', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,8,28,9), color = 'blue', linestyle='--', linewidth='1')
ax11.axvline(dt.datetime(2019,9,13,11), color = 'red', linestyle='--', linewidth='1')

ax12.axvline(dt.datetime(2020,8,30,11), color = 'red', linestyle='--', linewidth='1')
ax12.axvline(dt.datetime(2020,9,15,9), color = 'blue', linestyle='--', linewidth='1')
ax12.axvline(dt.datetime(2020,9,21,11), color = 'red', linestyle='--', linewidth='1')

#subplot 1
plt.setp(ax11.get_xticklabels(), visible=True)
ax11.set_ylabel ('$H_o\ [m]$', size = 12)
ax11.grid(True, ls='--')
ax11.plot(xs, df['ho'], linewidth = 1, color = 'k')

plt.setp(ax12.get_xticklabels(), visible=True)
ax12.grid(True, ls='--')
ax12.plot(xs, df['ho'], linewidth = 1, color = 'k')

ax11.spines['right'].set_visible(False)
ax12.spines['left'].set_visible(False)
ax11.yaxis.tick_left()
ax11.tick_params(labeltop='off')
ax12.tick_params(labelleft = 'off')
ax12.tick_params(left = 'off')

【问题讨论】:

  • 好的,这是你的问题,你的 LENGTHY 问题,但为了帮助你,我需要一个最低限度的例子。你扔给我的东西实在是太多了……
  • 请提供最短代码以重现问题
  • 看起来你想使用类似的东西:fig, (ax1, ax2) = plt.subplots(1, 2,gridspec_kw={'width_ratios': [0.8, 0.2]})
  • 我注意到左边的子图每天都有刻度线,而右边的子图每周都有刻度线。如果我们让左边的子图占据 80% 的宽度,而右边的子图占据 20% 的宽度,它们怎么可能是相同的比例呢?

标签: python numpy matplotlib


【解决方案1】:

您的任务是双重的:首先,您希望子图的水平比例为 8 比 2。其次,您假设您想设置一个断轴。子图的水平比例可以通过gridspec_ratios=[4,1]处理,如cmets所示;第二个是应用来自Broken Axis 的断轴。竖线已被省略。

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as ticker
import datetime as dt
from datetime import datetime

csv = './data/Data_20220114.csv'
df = pd.read_csv(csv, header=None, names=['time', 'tide', 'ho', 'tp', 'lo', 'mwd'])
xp = [datetime.strptime(d, "%d/%m/%YT%H:%M") for d in df['time']]
xs = mdates.date2num(xp)
    months_fmt = mdates.DateFormatter('%d/%m/%Y\n')

fig, (ax11, ax12) = plt.subplots(1, 2, figsize=(12,3), gridspec_kw=dict(width_ratios=[4,1]), sharex=False)
fig.subplots_adjust(wspace=0.05)

ax11.plot(xs, df['ho'], linewidth = 1, color = 'k')
ax11.xaxis.set_major_locator(mdates.MonthLocator(interval=3))
ax11.xaxis.set_major_formatter(months_fmt)
plt.setp(ax11.get_xticklabels(), rotation=45, ha='right')
ax11.set_ylabel ('$H_o\ [m]$', size = 12)
ax11.grid(True, ls='--')

ax12.plot(xs[-1440:], df['ho'][-1440:], linewidth = 1, color = 'k')
ax12.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
ax12.xaxis.set_major_formatter(months_fmt)
plt.setp(ax12.get_xticklabels(), rotation=45, ha='right')
ax12.grid(True, ls='--')

ax11.spines.right.set_visible(False)
ax12.spines.left.set_visible(False)
ax11.yaxis.tick_left()
ax12.tick_params(labelleft=False)
ax12.yaxis.tick_right()

d = 0.8  # proportion of vertical to horizontal extent of the slanted line
kwargs = dict(marker=[(-1, -d), (1, d)], markersize=12,
              linestyle="none", color='k', mec='k', mew=1, clip_on=False)
ax11.plot([1, 1], [1, 0], transform=ax11.transAxes, **kwargs)
ax12.plot([0, 0], [1, 0], transform=ax12.transAxes, **kwargs)

plt.show()

【讨论】:

  • 非常感谢!这工作得很好
猜你喜欢
  • 2023-03-12
  • 1970-01-01
  • 2013-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-11
  • 2019-05-27
相关资源
最近更新 更多