利用Python进行数据分析笔记-时间序列(时区、周期、频率)

时区处理

时区可以理解为UTC的偏移(offset),例如,在夏令时,纽约时间落后于UTC时间四个小时,而在一年的其他时间里,纽约时间落后于UTC时间五个小时。

在python中,时区信息来自第三方的pytz库,这个库利用的是奥尔森数据库,这个数据库汇集了世界时区信息。这个信息对于历史数据很重要,因为夏令时(daylight saving time,DST)的交接日(transition date)取决于当地政府的心血来潮。在美国,自1900年后,夏令时的交接日已经被改了很多次。

关于pytz库的更多信息,需要查看相关的文档。本书中pandas包含了一些pytz的功能,除了时区的名字,其他的API都不用去查。时区名字可以通过下面的方法获得:

import pytz
pytz.common_timezones[-5:]
['US/Eastern', 'US/Hawaii', 'US/Mountain', 'US/Pacific', 'UTC']
# 从pytz中得到一个时区对象,使用pytz.timezone
tz = pytz.timezone('America/New_York')
tz
<DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>

1、时区定位和转换

默认的,pandas中的时间序列是time zone naive(朴素时区)。

import pandas as pd
import numpy as np
rng = pd.date_range('3/9/2012 9:30', periods=6, freq='D')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
ts
2012-03-09 09:30:00    0.070052
2012-03-10 09:30:00    0.721449
2012-03-11 09:30:00   -0.266241
2012-03-12 09:30:00   -1.022387
2012-03-13 09:30:00   -1.476888
2012-03-14 09:30:00    0.770954
Freq: D, dtype: float64
# 使用tz_localize方法,可以实现从朴素到本地化(naive to localized)的转变
# 定位时区
ts_utc = ts.tz_localize('UTC')
ts_utc
2012-03-09 09:30:00+00:00    0.070052
2012-03-10 09:30:00+00:00    0.721449
2012-03-11 09:30:00+00:00   -0.266241
2012-03-12 09:30:00+00:00   -1.022387
2012-03-13 09:30:00+00:00   -1.476888
2012-03-14 09:30:00+00:00    0.770954
Freq: D, dtype: float64

一旦时间序列被定位到某个时区,那么它就可以被转换为任何其他时区,使用tz_convert:

# 转换时区
ts_utc.tz_convert('America/New_York')
2012-03-09 04:30:00-05:00    0.070052
2012-03-10 04:30:00-05:00    0.721449
2012-03-11 05:30:00-04:00   -0.266241
2012-03-12 05:30:00-04:00   -1.022387
2012-03-13 05:30:00-04:00   -1.476888
2012-03-14 05:30:00-04:00    0.770954
Freq: D, dtype: float64

在处理时间序列的时候,我们可以先把时间定位到纽约时间,然后转换到柏林时间

# 定位纽约再转换成UTC时区
ts_eastern = ts.tz_localize('America/New_York')
ts_eastern.tz_convert('UTC')
2012-03-09 14:30:00+00:00    0.070052
2012-03-10 14:30:00+00:00    0.721449
2012-03-11 13:30:00+00:00   -0.266241
2012-03-12 13:30:00+00:00   -1.022387
2012-03-13 13:30:00+00:00   -1.476888
2012-03-14 13:30:00+00:00    0.770954
Freq: D, dtype: float64
# 转换到柏林时间
ts_eastern.tz_convert('Europe/Berlin')
2012-03-09 15:30:00+01:00    0.070052
2012-03-10 15:30:00+01:00    0.721449
2012-03-11 14:30:00+01:00   -0.266241
2012-03-12 14:30:00+01:00   -1.022387
2012-03-13 14:30:00+01:00   -1.476888
2012-03-14 14:30:00+01:00    0.770954
Freq: D, dtype: float64

tz_localize和tz_convert也是DatetimeIndex上的实例方法(instance methods)

ts.index.tz_localize('Asia/Shanghai')
DatetimeIndex(['2012-03-09 09:30:00+08:00', '2012-03-10 09:30:00+08:00',
               '2012-03-11 09:30:00+08:00', '2012-03-12 09:30:00+08:00',
               '2012-03-13 09:30:00+08:00', '2012-03-14 09:30:00+08:00'],
              dtype='datetime64[ns, Asia/Shanghai]', freq='D')

2、时区的操作-意识到时间戳对象

和时间序列或日期范围(date ranges)相似,单独的Timestamp object(时间戳对象)也能从朴素(即无时区)本地化为有时区的日期,然后就可以转换为其他时区了

stamp = pd.Timestamp('2011-03-12 04:00')
stamp_utc = stamp.tz_localize('utc')      # 定位本地的时区
stamp_utc.tz_convert('America/New_York')  # 转换成纽约时区
Timestamp('2011-03-11 23:00:00-0500', tz='America/New_York')
# 创建Timestamp的时候,我们可以传递一个时区
stamp_moscow = pd.Timestamp('2011-03-12 04:00', tz='Europe/Moscow')
stamp_moscow
Timestamp('2011-03-12 04:00:00+0300', tz='Europe/Moscow')

有时区的Timestamp对象内部存储了一个UTC时间戳,这个值是从Unix纪元(即1907年1月1日)到现在的纳秒;这个UTC值在即使换了不同的时区,也是不变的

stamp_utc.value
1299902400000000000
stamp_utc.tz_convert('America/New_York').value
1299902400000000000

在使用pandas的DateOffset对象进行算数运算的时候,如果夏令时存在,pandas也会考虑进去。这里我们构建一个时间戳,正好出现在夏令时转换前。首先,在变为夏令时的前30分钟

from pandas.tseries.offsets import Hour
stamp = pd.Timestamp('2012-03-12 01:30', tz='US/Eastern')
stamp
Timestamp('2012-03-12 01:30:00-0400', tz='US/Eastern')
stamp + Hour()
Timestamp('2012-03-12 02:30:00-0400', tz='US/Eastern')

变为夏令时的90分钟前

stamp = pd.Timestamp('2012-11-04 00:30', tz='US/Eastern')
stamp
Timestamp('2012-11-04 00:30:00-0400', tz='US/Eastern')
stamp + 2 * Hour()
Timestamp('2012-11-04 01:30:00-0500', tz='US/Eastern')

3、不同时区间的运算

如果两个不同时区的时间序列被合并,那么结果为UTC。因为时间戳是以UTC为背后机制的,这种变化是直接的,不需要手动转换

rng = pd.date_range('3/7/2012 9:30', periods=10, freq='B')  # freq='B'表示按上班时间
ts = pd.Series(np.random.randn(len(rng)), index=rng)
ts
2012-03-07 09:30:00    1.128677
2012-03-08 09:30:00    0.865172
2012-03-09 09:30:00    1.003891
2012-03-12 09:30:00    0.594445
2012-03-13 09:30:00   -0.779890
2012-03-14 09:30:00    0.561338
2012-03-15 09:30:00    0.101160
2012-03-16 09:30:00   -0.314883
2012-03-19 09:30:00   -0.385164
2012-03-20 09:30:00    0.708143
Freq: B, dtype: float64
ts1 = ts[:7].tz_localize('Europe/London')
ts2 = ts1[2:].tz_convert('Europe/Moscow')
result = ts1 + ts2

result.index
DatetimeIndex(['2012-03-07 09:30:00+00:00', '2012-03-08 09:30:00+00:00',
     
  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值