python - 如何将分钟和小时的刻度添加到对数秒的 y 轴?
问题描述
我的代码现在看起来像这样:
import math
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.pyplot import figure
rows = np.around(np.logspace(math.log10(50),math.log10(10000),8))
rows = rows.astype(int)
# Plot runtimes
sns.set_style("whitegrid")
plt.rcParams["font.family"] = "Times New Roman"
figure(num=None,figsize=(9, 6), dpi=160, facecolor='w', edgecolor='k')
runtime = np.zeros((3,len(rows)))
runtime[0]=[1,1,3,34,104,445,2000,8000]
runtime[1]=[4,20,100,5000,26000,200000,'nan','nan']
runtime[2]=[0.5,0.5,3,30,80,300,1300,5000]
extraticks=[60]
extravalue=[60]
plt.plot(rows,runtime[0], label="A", marker='o')
plt.plot(rows,runtime[1], label="B", marker='o')
plt.plot(rows,runtime[2], label="C", marker='o')
plt.xscale("log"), plt.yscale("log")
plt.xticks(rows, labels=rows)
#plt.yticks(list(plt.yticks()[0])+extraticks,list(plt.yticks()[0])+extravalue)
plt.xlabel("Sample size")
plt.ylabel("Runtime [s]")
plt.legend()
这给了我以下结果(我画了额外的线条来显示预期的结果):
我将如何添加那些额外的线条和刻度?正如您在注释行中看到的那样,我尝试了类似的方法,但它弄乱了我之前工作的刻度和标签。
解决方案
一个想法是为标签和额外的网格线使用次要的 y 刻度。一个特殊的格式化程序将标签显示为分钟、小时、天。(matplotlib 3.4 需要直接设置格式化程序,旧版本需要FunctionFormatter
设置自定义格式化程序)。可选地,可以为这些新刻度使用不同的颜色和字体大小。
为了在 10 5处省略重叠的 y 刻度标签,特殊的格式化程序可以测试该功率并设置一个空标签。仍然会绘制相应的网格线,因为仍然会有刻度位置。
import matplotlib.pyplot as plt
from matplotlib.ticker import FixedLocator, ScalarFormatter
import seaborn as sns
import numpy as np
def show_pow_10(x, pos):
power = np.log10(x)
return '' if power == 5 else f'$10^{power:.0f}$'
def show_day_hour_min(x, pos):
if x < 60:
return f'{x:.0f} s'
else:
x = np.round(x / 60)
if x < 60:
return f'{x:.0f} min'
else:
x = np.round(x / 60)
return f'{x:.0f} h'
rows = np.around(np.logspace(np.log10(50), np.log10(10000), 8))
rows = rows.astype(int)
# Plot runtimes
sns.set_style("whitegrid")
plt.rcParams["font.family"] = "Times New Roman"
plt.figure(num=None, figsize=(9, 6), dpi=160, facecolor='w', edgecolor='k')
ax = plt.gca()
runtime = np.zeros((3, len(rows)))
runtime[0] = [1, 1, 3, 34, 104, 445, 2000, 8000]
runtime[1] = [4, 20, 100, 5000, 26000, 200000, np.nan, np.nan]
runtime[2] = [0.5, 0.5, 3, 30, 80, 300, 1300, 5000]
# extraticks = [60, 60 * 60, 24 * 60 * 60]
extraticks = [60, 10*60, 60 * 60, 10*60*60, 24 * 60 * 60]
ax.plot(rows, runtime[0], label="A", marker='o')
ax.plot(rows, runtime[1], label="B", marker='o')
ax.plot(rows, runtime[2], label="C", marker='o')
ax.set_xscale("log")
ax.set_yscale("log")
ax.xaxis.set_major_locator(FixedLocator(rows))
ax.xaxis.set_major_formatter(ScalarFormatter())
ax.yaxis.set_major_formatter(show_pow_10)
ax.set_yticks(extraticks, minor=True)
ax.tick_params(axis='y', which='minor', labelcolor='dodgerblue', labelsize=9)
ax.yaxis.set_minor_locator(FixedLocator(extraticks))
ax.yaxis.set_minor_formatter(show_day_hour_min)
ax.set_xlabel("Sample size")
ax.set_ylabel("Runtime [s]")
ax.grid(True, which='minor', axis='y', color='dodgerblue', ls='--', lw=0.5, alpha=0.6)
ax.legend()
plt.show()
推荐阅读
- r - 如何处理重复并偏爱一个版本,但并非总是如此
- firebase - 错误:没有创建 Firebase 应用“[默认]” - 调用 firebase.initializeapp() - 反应原生 Android
- android - 为什么片段和视图不会混淆?
- python - 在正则表达式中转义正斜杠没有什么效果?
- php - Laravel 雄辩的外表平均分
- c# - 对象类型未实现 IComparable
- php - 致命错误:未捕获的错误:调用未定义的方法 Closure::index() php
- css - 如何将 Flexbox 与 Web 组件和影子 DOM 一起使用
- typescript - 尝试在使用打字稿做出本机反应时导入 gql 文件错误 2307
- python - 网页拒绝连接