【问题标题】:Pandas plot function ignores timezone of timeseries熊猫绘图功能忽略时间序列的时区
【发布时间】:2012-10-13 09:10:58
【问题描述】:

使用 pandas 的内置绘图功能绘制时间序列时,它似乎忽略了我的索引的时区:它始终使用 UTC 时间作为 x 轴。一个例子:

import numpy as np
import matplotlib.pyplot as plt
from pandas import rolling_mean, DataFrame, date_range

rng = date_range('1/1/2011', periods=200, freq='S', tz="UTC")
data = DataFrame(np.random.randn(len(rng), 3), index=rng, columns=['A', 'B', 'C'])
data_cet = data.tz_convert("CET")

# plot with data in UTC timezone
fig, ax = plt.subplots()
data[["A", "B"]].plot(ax=ax, grid=True)
plt.show()

# plot with data in CET timezone, but the x-axis remains the same as above
fig, ax = plt.subplots()
data_cet[["A", "B"]].plot(ax=ax, grid=True)
plt.show()

情节没有改变,虽然索引有:

In [11]: data.index[0]
Out[11]: <Timestamp: 2011-01-01 00:00:00+0000 UTC, tz=UTC>
In [12]: data_cet.index[0]
Out[12]: <Timestamp: 2011-01-01 01:00:00+0100 CET, tz=CET>

我应该提交一个错误,还是我错过了什么?

【问题讨论】:

  • Here 是如何绕过这个错误的!

标签: python pandas


【解决方案1】:
from pytz import timezone as ptz
import matplotlib as mpl
...
data.index = pd.to_datetime(data.index, utc=True).tz_localize(tz=ptz('<your timezone>'))
...
mpl.rcParams['timezone'] = data.index.tz.zone

... 之后 matplotlib 打印为该区域而不是 UTC。

但是!请注意,如果您需要注释,注释的 x 位置仍然需要采用 UTC,即使传递给 data.loc[] 或 data.at[] 的字符串将被假定在设置的时区中!

例如,我需要显示一系列标有时间戳的垂直线: (这是在大多数情节调用之后,并注意 sels 中的时间戳字符串是 UTC)

sels = ['2019-03-21 3:56:28',
         '2019-03-21 4:00:30',
         '2019-03-21 4:05:55',
         '2019-03-21 4:13:40']
ax.vlines(sels,125,145,lw=1,color='grey') # 125 was bottom, 145 was top in data units
for s in sels:
    tstr = pd.to_datetime(s, utc=True)\
    .astimezone(tz=ptz(data.index.tz.zone))\
    .isoformat().split('T')[1].split('+')[0]
    ax.annotate(tstr,xy=(s,125),xycoords='data',
              xytext=(0,5), textcoords='offset points', rotation=90,
              horizontalalignment='right', verticalalignment='bottom')

这会在sels 中手动选择的时间放置灰色垂直线,并以当地时区的小时、分钟和秒标记它们。 (.split()[] 业务丢弃了.isoformat() 字符串中的日期和时区信息)。

但是当我需要在sels中使用相同的s从数据中实际获取相应的值时,我不得不使用有点尴尬的:

data.tz_convert('UTC').at[s]

而只是

data.at[s]

由于pandas 解释s 是在data.index.tz 时区中,所以以KeyError 失败,并且如此解释,时间戳超出data 的内容范围

【讨论】:

    【解决方案2】:

    如何处理UTC到本地时间的转换

    import time
    import matplotlib.dates
    …
    tz = pytz.timezone(time.tzname[0])
    …
    ax.xaxis.set_major_locator(matplotlib.dates.HourLocator(interval=1, tz=tz))
    ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%H', tz=tz))
    

    【讨论】:

    • 对我不起作用 - 只是不断显示 UTC 时间。也试过ax.xaxis_date(tz),也没有运气。但我最终找到了一个解决方案,虽然很尴尬。 (见下文)
    【解决方案3】:

    这绝对是一个错误。我在github 上创建了一份报告。原因是在内部,pandas 将常规频率 DatetimeIndex 转换为 PeriodIndex 以挂钩到 pandas 中的格式化程序/定位器,而目前 PeriodIndex 不保留时区信息。 请继续关注修复。

    【讨论】:

    • 4 年后...有什么解决办法吗?
    • 5 年后won't fix!
    猜你喜欢
    • 2019-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 2014-12-17
    相关资源
    最近更新 更多