在Python中跳过不需要的日期的同时绘制时间与日期的关系 [英] Plotting times versus dates while skipping unwanted dates in Python
问题描述
我想制作一个监视我的5000米进度的程序.受到图1:上面代码中的 fig_1
.图2:上面代码中的 fig_2
.
- 为什么用较低或较高的值无法正确绘制y轴?
- 如何防止
equidate_ax
函数重复自身而跳过不必要的日期?
如果有人可以帮助清理我的烂摊子,我将不胜感激.
结合所链接问题的答案:
基本上,您必须确保matplotlib无法猜测x轴的格式,但是可以猜测y轴的格式.使用此matplotlib,您将不会变得聪明,也不想添加不想在x轴上显示的日期,但同时会变得聪明,并在y轴上为您排序时间.
__future__导入部门的 从matplotlib导入pyplot作为plt从matplotlib.ticker导入FuncFormatter将matplotlib.dates导入为mdates将numpy导入为np导入日期时间为dtdef DistVel2Time(距离,velocity_kph):velocity_ms = velocity_kph/3.6time_sec =距离/速度_ms小时=整数(time_sec//3600)分钟= int((time_sec%3600)//60)秒=整数(time_sec%60)#注意我在这里返回一个timedelta对象返回dt.timedelta(分钟=分钟,秒=秒)#我们必须在这里选择一种可解释的数据类型,只需花费所需的总时间(以秒为单位)times = [[[5000,13),(5000,15),(5000,14)]中a,b的DistVel2Time(a,b).total_seconds()对于a,b#在这里我们要确保matplotlib无法解释它,所以我们直接使用字符串#根据需要更改格式date = [(2019,2,1),(2019,2,2),(2019,2,7)]中ymd的ymd的日期= ["%00d.%00d.%000d#来自https://stackoverflow.com/questions/48294332/plot-datetime-timedelta-using-matplotlib-and-python的格式化功能def format_func(x,pos):小时= int(x//3600)分钟= int((x%3600)//60)秒= int(x%60)返回"{:d}:{:02d}:{:02d}".格式(小时,分钟,秒)格式化程序= FuncFormatter(format_func)无花果= plt.figure()斧= fig.add_subplot(1、1、1)ax.plot(日期,时间,'o--')ax.yaxis.set_major_formatter(格式化程序)plt.show()
它将产生如下图:
I want to make a program that monitors my 5000 meters progress. Inspired by this and this, I tried to make it work by combining some of the answers without any luck.
from __future__ import division
from matplotlib import pyplot as plt
from matplotlib.ticker import FuncFormatter
import matplotlib.dates as mdates
import numpy as np
import datetime as dt
def equidate_ax(fig, ax, dates, fmt="%d.%m.%Y", label="Date"):
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()
def DistVel2Time(distance, velocity_kph):
velocity_ms = velocity_kph / 3.6
time_sec = distance / velocity_ms
hours = int(time_sec//3600)
minutes = int((time_sec%3600)//60)
seconds = int(time_sec%60)
return "{:02d}:{:02d}".format(minutes, seconds)
times = [DistVel2Time(a, b) for a, b in [(5000, 13), (5000, 15), (5000, 14)]]
dates = [dt.datetime(year, month, day) for year, month, day in [(2019,2,1), (2019,2,2), (2019,2,7)]]
fig_1, ax_1 = plt.subplots()
ax_1.plot(dates, times, 'o--')
ax_1.xaxis_date()
ax_1.xaxis.set_major_formatter(mdates.DateFormatter('%d.%m.%Y'))
#ax_1.yaxis_date()
#ax_1.yaxis.set_major_formatter(mdates.DateFormatter("%M:%S"))
fig_1.autofmt_xdate()
plt.show()
fig_2, ax_2 = plt.subplots()
ax_2.plot(dates, times, 'D--')
ax_2.xaxis_date()
ax_2.xaxis.set_major_formatter(mdates.DateFormatter('%d.%m.%Y'))
equidate_ax(fig_2, ax_2, dates)
plt.show()
fig_1.savefig('fig1.png')
fig_2.savefig('fig2.png')
I stole the equidate_ax
from @ascripter (from the second link) because I would like to skip all dates that I do not run.
If I run this piece of code, and save the figures, I end up getting the following two figures that are rather strange, as the y-axis does not distinguish between lower or higher values (Figures 1 and 2), and the x-axis for Figure 2 is repeating itself.
Figure 1: fig_1
from the code above.
Figure 2: fig_2
from the code above.
- Why is not the y-axis plotting correctly in terms of lower or higher values?
- How can I prevent the
equidate_ax
function from repeating itself and rather skip the unwanted dates?
If anyone could help cleaning up my mess, I would be grateful.
Combining the answers from the questions linked:
You basically have to make sure that matplotlib cannot guess the format of the x-axis but can guess the format of the y-axis. With this matplotlib will not try to be smart and add dates you do not want to display on the x-axis but at the same time will be smart and sort the times for you on the y-axis.
from __future__ import division
from matplotlib import pyplot as plt
from matplotlib.ticker import FuncFormatter
import matplotlib.dates as mdates
import numpy as np
import datetime as dt
def DistVel2Time(distance, velocity_kph):
velocity_ms = velocity_kph / 3.6
time_sec = distance / velocity_ms
hours = int(time_sec//3600)
minutes = int((time_sec%3600)//60)
seconds = int(time_sec%60)
# note that I return a timedelta object here
return dt.timedelta(minutes=minutes, seconds=seconds)
# we have to choose a interpretable data-type here, simply take the total time needed in seconds
times = [ DistVel2Time(a, b).total_seconds() for a, b in [(5000, 13), (5000, 15), (5000, 14)]]
# here we want to make sure that matplotlib cannot interpret it so we use strings directly
# change the format as required
dates = [ "%00d.%00d.%000d" % ymd for ymd in [(2019,2,1), (2019,2,2), (2019,2,7)]]
# the formatting function taken from https://stackoverflow.com/questions/48294332/plot-datetime-timedelta-using-matplotlib-and-python
def format_func(x, pos):
hours = int(x//3600)
minutes = int((x%3600)//60)
seconds = int(x%60)
return "{:d}:{:02d}:{:02d}".format(hours, minutes, seconds)
formatter = FuncFormatter(format_func)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(dates, times, 'o--')
ax.yaxis.set_major_formatter(formatter)
plt.show()
It will produce a plot like this:
这篇关于在Python中跳过不需要的日期的同时绘制时间与日期的关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!