Eri*_*got 10 python timezone plot matplotlib python-datetime
我有数据点,其横坐标是datetime.datetime
具有时区的对象(它们tzinfo
碰巧是bson.tz_util.FixedOffset
通过MongoDB获得的).
当我用它们绘图时scatter()
,刻度标签的时区是什么?
改变timezone
在matplotlibrc
不改变显示的情节什么(我一定是误解了对时区的讨论的Matplotlib文档中).
我尝试了一点plot()
(而不是scatter()
).给定一个日期时,它会绘制它并忽略时区.但是,当给定多个日期时,它使用固定的时区,但是如何确定?我在文档中找不到任何内容.
最后,plot_date()
应该是这些时区问题的解决方案吗?
问题已经在评论中得到了回答.但是我自己仍然在与时区挣扎.为了清楚起见,我尝试了所有组合.我认为你有两种主要的方法,取决于你的日期时间对象是否已经在所需的时区或在不同的时区,我试着在下面描述它们.有可能我仍然错过/混合了一些东西..
时间戳(日期时间对象):以UTC为 期望显示:在特定时区
rcParam['timezone']
为UTC为我)时间戳(日期时间对象):在特定时区中 所需显示:在不同的特定时区
tzinfo=
)输入绘图函数datetime对象如果您正在使用plot_date(),您也可以传入tz关键字,但对于散点图,这是不可能的.
当您的源数据包含unix时间戳时,请务必明智地选择是否使用datetime.datetime.utcfromtimestamp()
utc:fromtimestamp()
如果您要使用matplotlib时区功能.
这是我做过的实验(在这个例子中就是scatter()),这可能有点难以理解,但只是写在这里给任何关心的人.注意第一个点出现的时间(x轴不会在每个子图的同一时间开始):
源代码:
import time,datetime,matplotlib
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.dates as mdates
from dateutil import tz
#y
data = np.array([i for i in range(24)])
#create a datetime object from the unix timestamp 0 (epoch=0:00 1 jan 1970 UTC)
start = datetime.datetime.fromtimestamp(0)
# it will be the local datetime (depending on your system timezone)
# corresponding to the epoch
# and it will not have a timezone defined (standard python behaviour)
# if your data comes as unix timestamps and you are going to work with
# matploblib timezone conversions, you better use this function:
start = datetime.datetime.utcfromtimestamp(0)
timestamps = np.array([start + datetime.timedelta(hours=i) for i in range(24)])
# now add a timezone to those timestamps, US/Pacific UTC -8, be aware this
# will not create the same set of times, they do not coincide
timestamps_tz = np.array([
start.replace(tzinfo=tz.gettz('US/Pacific')) + datetime.timedelta(hours=i)
for i in range(24)])
fig = plt.figure(figsize=(10.0, 15.0))
#now plot all variations
plt.subplot(711)
plt.scatter(timestamps, data)
plt.gca().set_xlim([datetime.datetime(1970,1,1), datetime.datetime(1970,1,2,12)])
plt.gca().set_title("1 - tzinfo NO, xaxis_date = NO, formatter=NO")
plt.subplot(712)
plt.scatter(timestamps_tz, data)
plt.gca().set_xlim([datetime.datetime(1970,1,1), datetime.datetime(1970,1,2,12)])
plt.gca().set_title("2 - tzinfo YES, xaxis_date = NO, formatter=NO")
plt.subplot(713)
plt.scatter(timestamps, data)
plt.gca().set_xlim([datetime.datetime(1970,1,1), datetime.datetime(1970,1,2,12)])
plt.gca().xaxis_date('US/Pacific')
plt.gca().set_title("3 - tzinfo NO, xaxis_date = YES, formatter=NO")
plt.subplot(714)
plt.scatter(timestamps, data)
plt.gca().set_xlim([datetime.datetime(1970,1,1), datetime.datetime(1970,1,2,12)])
plt.gca().xaxis_date('US/Pacific')
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M(%d)'))
plt.gca().set_title("4 - tzinfo NO, xaxis_date = YES, formatter=YES")
plt.subplot(715)
plt.scatter(timestamps_tz, data)
plt.gca().set_xlim([datetime.datetime(1970,1,1), datetime.datetime(1970,1,2,12)])
plt.gca().xaxis_date('US/Pacific')
plt.gca().set_title("5 - tzinfo YES, xaxis_date = YES, formatter=NO")
plt.subplot(716)
plt.scatter(timestamps_tz, data)
plt.gca().set_xlim([datetime.datetime(1970,1,1), datetime.datetime(1970,1,2,12)])
plt.gca().set_title("6 - tzinfo YES, xaxis_date = NO, formatter=YES")
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M(%d)'))
plt.subplot(717)
plt.scatter(timestamps_tz, data)
plt.gca().set_xlim([datetime.datetime(1970,1,1), datetime.datetime(1970,1,2,12)])
plt.gca().xaxis_date('US/Pacific')
plt.gca().set_title("7 - tzinfo YES, xaxis_date = YES, formatter=YES")
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M(%d)'))
fig.tight_layout(pad=4)
plt.subplots_adjust(top=0.90)
plt.suptitle(
'Matplotlib {} with rcParams["timezone"] = {}, system timezone {}"
.format(matplotlib.__version__,matplotlib.rcParams["timezone"],time.tzname))
plt.show()
Run Code Online (Sandbox Code Playgroud)
如果像我一样,您在尝试让具有时区感知能力的Pandas DataFrame正确绘图时遇到这个问题,@pseyfert 使用带时区的格式化程序的评论也很划算。以下是 的示例pandas.plot
,显示了从 EST 过渡到 EDT 时的一些要点:
df = pd.DataFrame(
dict(y=np.random.normal(size=5)),
index=pd.DatetimeIndex(
start='2018-03-11 01:30',
freq='15min',
periods=5,
tz=pytz.timezone('US/Eastern')))
Run Code Online (Sandbox Code Playgroud)
注意当我们过渡到夏令时时区是如何变化的:
> [f'{t:%T %Z}' for t in df.index]
['01:30:00 EST',
'01:45:00 EST',
'03:00:00 EDT',
'03:15:00 EDT',
'03:30:00 EDT']
Run Code Online (Sandbox Code Playgroud)
现在,绘制它:
df.plot(style='-o')
formatter = mdates.DateFormatter('%m/%d %T %Z', tz=df.index.tz)
plt.gca().xaxis.set_major_formatter(formatter)
plt.show()
Run Code Online (Sandbox Code Playgroud)
附注:
不知道为什么有些日期(EST 日期)看起来像粗体,但大概 matplotlib 的内部结构多次渲染标签并且位置改变一两个像素......以下确认格式化程序是多次调用相同的时间戳:
class Foo(mdates.DateFormatter):
def __init__(self, *args, **kwargs):
super(Foo, self).__init__(*args, **kwargs)
def strftime(self, dt, fmt=None):
s = super(Foo, self).strftime(dt, fmt=fmt)
print(f'out={s} for dt={dt}, fmt={fmt}')
return s
Run Code Online (Sandbox Code Playgroud)
并检查输出:
df.plot(style='-o')
formatter = Foo('%F %T %Z', tz=df.index.tz)
plt.gca().xaxis.set_major_formatter(formatter)
plt.show()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4941 次 |
最近记录: |