时间序列是很重要的。时间序列(time series)数据是一种重要的结构化数据格式。时间序列的意义取决于具体的应用场景,主要有以下几种:

  • 时间戳(timestamp),特定的时刻
  • 固定时期(period),如2015年全年
  • 时间间隔(interval),由起始和结束时间戳表示。就是说,时期可以是时间间隔的特例。
  • 实验或过程时间,每个时间点都是相对于特定起始时间的一个度量。例如,自从放入烤箱时起,每秒钟饼干的直径。

pandas提供了一组标准的时间序列处理工具和数据算法。因此可以高效处理非常大的时间序列,轻松进行切片/切块、聚合、对定期/不定期的时间序列进行重采样等。也就是说,大部分都对金融和经济数据尤为有用,当然也可以用它们来分析服务器日志数据。

1、日期和时间数据类型及工具

Python标准库中包含用于日期(date)、时间(time)数据的数据类型。而且还有日历方面的功能。主要会用到datetime、time、calendar模块。

#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from datetime import datetimenow = datetime.now()
#datetime以毫秒形式储存时间
print now,now.year,now.month,now.day,now.microsecond,'\n'
#print datetime(2015,12,17,20,00,01,555555) #设置一个时间
#datetime.timedelta表示两个datetime对象之间的时间差
#换句话说,datetime格式可以相相减
delta = datetime(2011,1,7) - datetime(2008,6,24,8,15)
print delta
#把注意下面是days And seconds
print dt.timedelta(926,56700)
print delta.days
print delta.seconds
#下面是错误的
#print delta.minutes
start = datetime(2011,1,7)
#参数分别为days,seconds,microseconds(微秒),milliseconds(毫秒),minutes,hours,weeks,除了微秒小数自动四舍五入之外,其他的都能自动转换为其他度量
print start + dt.timedelta(1,20,0.5,5,10,10,0)
>>>
2015-12-17 20:24:21.829000 2015 12 17 829000 

926 days, 15:45:00
926 days, 15:45:00
926
56700
2011-01-08 10:10:20.005001
[Finished in 0.6s]

datetime中的数据类型有:

  • 字符串和datetime的相互转换

利用str或者strftime方法(传入一个格式化字符串),datetime对象和pandas中timestamp对象就可以转换为字符串:

#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from datetime import datetime
from dateutil.parser import parsestamp = datetime(2011,1,3)
print str(stamp),'\n'
#看一下下面的字符,很有意思,自己不小心打错了,运行仍然是正确的
print stamp.strftime('&Y-%m-%d')
print stamp.strftime('%Y-%m-%d'),'\n'
value = '2011-01-03'
print datetime.strptime(value,'%Y-%m-%d') #注意这是datetime函数的函数,不是模块的函数
datestrs = ['7/6/2011','8/6/2011']
print [datetime.strptime(x,'%m/%d/%Y') for x in datestrs]
#上面将字符串转化为最常用的格式,但是米次都自己写出来有点麻烦,可以用dateutil这个第三方包中的parser.parse方法
print parse('2011-01-03')
#dateutil可以几乎解析所有能够理解的日期表示形式(很可惜中文不行)
#这个应该是很实用的
print parse('2011/01/03')
print parse('Jan 31,1997 10:45 PM')
#国际通用格式中,日出现在月的前面,传入dayfirst = True即可
print parse('6/12/2011',dayfirst = True),'\n'
#pandas通常是用于处理成组日期的,不管这些日期是DataFrame的行还是列。
print pd.to_datetime(datestrs),'\n'
idx = pd.to_datetime(datestrs + [None])
print idx
print idx[2] #这里应该是NaT(Not a Time)
print pd.isnull(idx)
#parse是一个不完美的工具,比如下面
print parse('42')
>>>
2011-01-03 00:00:00 

&Y-01-03
2011-01-03

2011-01-03 00:00:00
[datetime.datetime(2011, 7, 6, 0, 0), datetime.datetime(2011, 8, 6, 0, 0)]
2011-01-03 00:00:00
2011-01-03 00:00:00
1997-01-31 22:45:00
2011-12-06 00:00:00

<class 'pandas.tseries.index.DatetimeIndex'>
[2011-07-06 00:00:00, 2011-08-06 00:00:00]
Length: 2, Freq: None, Timezone: None

<class 'pandas.tseries.index.DatetimeIndex'>
[2011-07-06 00:00:00, ..., NaT]
Length: 3, Freq: None, Timezone: None
0001-255-255 00:00:00
[False False  True]
2042-12-17 00:00:00
[Finished in 0.6s]

下面是日期的一些格式:

datetime对象还有一些特定于当前环境(位于不同国家或使用不同语言系统)的格式化选项。估计用的少?

2、时间序列基础

pandas最基本的时间序列类型就是以时间戳(通常用Python字符串或datatime对象表示)为索引的Series。

#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas import Series,DataFrame
from datetime import datetime
from dateutil.parser import parsedates = [datetime(2011,1,2),datetime(2011,1,5),datetime(2011,1,7),
datetime(2011,1,8),datetime(2011,1,10),datetime(2011,1,12)]
#print dates
ts = Series(np.random.randn(6),index = dates)
print ts,'\n'
#这些datetime对象实际上是被放在一个DatetimeIndex中的。现在,变量ts就成为了TimeSeries了。
print type(ts)
print ts.index,'\n'
#没必要显示使用TimeSeries的构造函数。当创建一个带有DatetimeIndex的Series时,pandas就会知道该对象是一个时间序列
print ts + ts[::2]
#pandas用NumPy的datetime64数据类型以纳秒形式存储时间戳:
print ts.index.dtype
#DatetimeIndex中的各个标量值是pandas的Timestamp
stamp = ts.index[0]
print stamp
#只要有需要,TimeStamp可以随时自动转换为datetime对象。此外,还可以存储频率信息,且知道如何执行时区转换以及其他操作
>>>
2011-01-02   -1.2671082011-01-05   -0.4500982011-01-07    0.7848502011-01-08    0.0247222011-01-10    0.6386632011-01-12    0.246022 

<class 'pandas.core.series.TimeSeries'>
<class 'pandas.tseries.index.DatetimeIndex'>
[2011-01-02 00:00:00, ..., 2011-01-12 00:00:00]
Length: 6, Freq: None, Timezone: None

2011-01-02   -2.534216
2011-01-05         NaN
2011-01-07    1.569701
2011-01-08         NaN
2011-01-10    1.277326
2011-01-12         NaN
datetime64[ns]
2011-01-02 00:00:00
[Finished in 0.7s]

索引、选取、子集构造

TimeSeries是Series的一个子类,所以在索引以及数据选取方面跟Series一样。

stamp = ts.index[2]
print ts[stamp],'\n'
#还有更方便的用法,传入可以被解释为日期的字符串
print ts['1/10/2011']
print ts['20110110'],'\n'
#对于较长的时间序列,只需传入“年”或“年月”即可轻松选取数据切片
long_ts = Series(np.random.randn(1000),index = pd.date_range('1/1/2000',periods = 1000))
#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas import Series,DataFrame
from datetime import datetime
from dateutil.parser import parse
import timeprint long_ts,'\n'
print long_ts['2001'],'\n'
print long_ts['2001-05'],'\n'
#通过日期进行切片的方式只对规则Series有效:
print ts[datetime(2011,1,7):],'\n'
#由于大部分时间序列数据都是按照时间先后排序的,因此你可以用不存在于该时间序列中的时间戳对其进行切片(即范围查询)
#就是说,本来1/6/2011不在index中,却可以用来当作范围
print ts['1/6/2011':'1/11/2011'],'\n' #这里可以传入字符串日期、datetime或者Timestampprint 'This is time and localtime'
print "time.time(): %f " %  time.time()
print time.localtime( time.time() )
print time.asctime( time.localtime(time.time()) )
ltime=time.localtime(int(time.time()))   #time.time()不能直接运用strftime进行转换
print time.strftime("%Y-%m-%d %H:%M:%S", ltime)
#time asctime() 函数接受时间元组并返回一个可读的形式为"Tue Dec 11 18:07:14 2008"
print 'over','\n'#还有一个等价方法截取两个日期之间的TimeSeries.
print ts.truncate(after = '1/9/2011'),'\n'#上面这些对DataFrame也有效
dates = pd.date_range('1/1/2000',periods = 100,freq = 'W-WED') #这里的freq是按照星期进行增加
long_df = DataFrame(np.random.randn(100,4),index = dates,columns = ['Colorado','Texas','New York','Ohio'])
print long_df.ix['2001-05']
>>>
0.0751316698811 
-0.622706612554-0.622706612554 

2000-01-01   -1.646726
2000-01-02    1.531423
2000-01-03    0.251503
2000-01-04    0.938951
2000-01-05    0.647967
2000-01-06    0.696173
2000-01-07   -1.372519
2000-01-08   -1.398277
2000-01-09   -0.679975
2000-01-10   -0.801375
2000-01-11   -0.241165
2000-01-12   -0.332811
2000-01-13   -0.337774
2000-01-14    0.826756
2000-01-15   -0.279239
...
2002-09-12   -0.097634
2002-09-13    2.222456
2002-09-14    0.042517
2002-09-15    0.266974
2002-09-16    0.038329
2002-09-17   -1.524744
2002-09-18    1.476706
2002-09-19    0.108336
2002-09-20    0.016759
2002-09-21   -0.072676
2002-09-22   -0.960545
2002-09-23    0.520699
2002-09-24   -1.188202
2002-09-25    1.669166
2002-09-26   -0.043997
Freq: D, Length: 1000

2001-01-01   -0.168866
2001-01-02   -0.273377
2001-01-03    0.094258
2001-01-04   -0.979666
2001-01-05    0.947706
2001-01-06    0.666709
2001-01-07    0.451145
2001-01-08   -0.301992
2001-01-09    0.272385
2001-01-10   -0.255775
2001-01-11   -0.321916
2001-01-12    1.894119
2001-01-13    0.582272
2001-01-14   -1.102707
2001-01-15    0.019423
...
2001-12-17   -0.243563
2001-12-18    1.757564
2001-12-19   -0.145106
2001-12-20   -0.579629
2001-12-21   -0.431069
2001-12-22    0.480805
2001-12-23   -0.651905
2001-12-24    0.702051
2001-12-25   -0.384549
2001-12-26   -1.077664
2001-12-27   -0.972768
2001-12-28    1.001220
2001-12-29    0.418016
2001-12-30    0.567361
2001-12-31   -0.811610
Freq: D, Length: 365

2001-05-01   -0.071521
2001-05-02    0.402344
2001-05-03   -0.568929
2001-05-04    0.227754
2001-05-05    0.194631
2001-05-06   -0.407669
2001-05-07   -1.407606
2001-05-08   -0.804147
2001-05-09    0.050445
2001-05-10   -0.604275
2001-05-11    0.270760
2001-05-12    0.000804
2001-05-13   -0.348938
2001-05-14   -1.626158
2001-05-15    0.084629
2001-05-16   -0.376655
2001-05-17    1.913789
2001-05-18    2.497594
2001-05-19    0.818446
2001-05-20    0.067115
2001-05-21   -0.993827
2001-05-22    0.940616
2001-05-23   -0.951763
2001-05-24   -0.806228
2001-05-25    0.441872
2001-05-26    0.067010
2001-05-27   -1.903360
2001-05-28   -0.400990
2001-05-29    0.257146
2001-05-30    0.785503
2001-05-31   -1.129024
Freq: D

2011-01-07    0.075132
2011-01-08   -0.985630
2011-01-10   -0.622707
2011-01-12   -1.356095

2011-01-07    0.075132
2011-01-08   -0.985630
2011-01-10   -0.622707

This is time and localtime
time.time(): 1450362054.149000
time.struct_time(tm_year=2015, tm_mon=12, tm_mday=17, tm_hour=22, tm_min=20, tm_sec=54, tm_wday=3, tm_yday=351, tm_isdst=0)
Thu Dec 17 22:20:54 2015
2015-12-17 22:20:54
over

2011-01-02   -0.772858
2011-01-05   -0.908074
2011-01-07    0.075132
2011-01-08   -0.985630

Colorado     Texas  New York      Ohio
2001-05-02  0.303341  0.026978 -0.036389  0.463034
2001-05-09 -1.573227 -0.283074 -0.882382 -1.207936
2001-05-16  1.520804 -0.838297  0.725690  1.240092
2001-05-23  1.297194 -0.516198 -0.022075 -0.876630
2001-05-30 -1.629426  1.022547 -0.131823 -0.621269
[Finished in 0.7s]

  • 带有重复索引的时间序列
#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas import Series,DataFrame
from datetime import datetime
from dateutil.parser import parse
import time#注意下面的DatetimeIndex生成方式
dates = pd.DatetimeIndex(['1/1/2000','1/2/2000','1/2/2000','1/2/2000','1/3/2000'])
dup_ts = Series(np.arange(5),index = dates)
print dup_ts,'\n'
#通过检唯一的测is_unique属性,我们就可以知道它不是
print dup_ts.index.is_unique,'\n'
#此时若索引,得到的可能是标量值,也可能是切片
print dup_ts['1/2/2000'],'\n'
print dup_ts['1/3/2000']
#假如你想要对具有非
#唯一时间戳的数据进行聚合一个办法是使用groupby,并传入level = 0
grouped = dup_ts.groupby(level = 0)
print grouped.mean(),'\n'
print grouped.count()
>>>
2000-01-01    02000-01-02    12000-01-02    22000-01-02    32000-01-03    4 

False

2000-01-02    1
2000-01-02    2
2000-01-02    3

4
2000-01-01    0
2000-01-02    2
2000-01-03    4

2000-01-01    1
2000-01-02    3
2000-01-03    1
[Finished in 1.3s]

3、日期的范围、频率以及移动

有时候需要用相对固定的频率对数据进行分析,比如每月、每天等。幸运的是,pandas有一整套标准时间序列频率以及用于重采样、频率推断、生成固定频率日期范围的工具。

#定义列表
dates = [datetime(2011,1,2),datetime(2011,1,5),datetime(2011,1,7),
datetime(2011,1,8),datetime(2011,1,10),datetime(2011,1,12)]
#print dates
ts = Series(np.random.randn(6),index = dates)
#print ts
#下面进行重采样,得到具有固定时间频率(每天)的时间序列,当让这样的话就会产生缺失值
print ts.resample('D')#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas import Series,DataFrame
from datetime import datetime
from dateutil.parser import parse
import time#定义列表
dates = [datetime(2011,1,2),datetime(2011,1,5),datetime(2011,1,7),
datetime(2011,1,8),datetime(2011,1,10),datetime(2011,1,12)]
#print dates
ts = Series(np.random.randn(6),index = dates)
#print ts
#下面进行重采样,得到具有固定时间频率(每天)的时间序列,当让这样的话就会产生缺失值
print ts.resample('D') #频率的转换(或重采样)主题较大,后面再说
>>>
2011-01-02   -0.9566272011-01-03         NaN2011-01-04         NaN2011-01-05    0.1305652011-01-06         NaN2011-01-07    0.0902702011-01-08    0.7538812011-01-09         NaN2011-01-10   -0.7335142011-01-11         NaN2011-01-12   -0.200039Freq: D[Finished in 1.2s]

  • 生成日期范围
#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas import Series,DataFrame
from datetime import datetime
from dateutil.parser import parse
import time#pandas.date_range会生成指定长度的DatetimeIndex
index = pd.date_range('4/1/2015','6/1/2015')
print index,'\n'
#默认情况下,date_range产生按天计算的时间点,当然可以传入开始或结束日期,还得传入一个表示一段时间的数字
print pd.date_range('1/1/2016',periods = 31),'\n'
#开始和结束定义了日期索引的严格边界,如果你想要生成一个由每月最后一个工作日组成的日期索引,可以传入‘BM’(business end of month)
#这样就只会包含时间间隔内(或者放好在时间边界上)符合频率要求的日期:
print pd.date_range('12/18/2015','1/1/2016',freq = 'BM'),'\n'
#date_range默认保留起始和结束时间戳信息
print pd.date_range('5/2/2015 12:12:12',periods = 5)
#有时,虽然起始和结束带有时间信息,但是可以用normalize = True把它们吧变为00:00:00
print pd.date_range('5/2/2015 12:12:12',periods = 5,normalize = True)
>>>
<class 'pandas.tseries.index.DatetimeIndex'>[2015-04-01 00:00:00, ..., 2015-06-01 00:00:00]Length: 62, Freq: D, Timezone: None 

<class 'pandas.tseries.index.DatetimeIndex'>
[2016-01-01 00:00:00, ..., 2016-01-31 00:00:00]
Length: 31, Freq: D, Timezone: None

<class 'pandas.tseries.index.DatetimeIndex'>
[2015-12-31 00:00:00]
Length: 1, Freq: BM, Timezone: None

<class 'pandas.tseries.index.DatetimeIndex'>
[2015-05-02 12:12:12, ..., 2015-05-06 12:12:12]
Length: 5, Freq: D, Timezone: None
<class 'pandas.tseries.index.DatetimeIndex'>
[2015-05-02 00:00:00, ..., 2015-05-06 00:00:00]
Length: 5, Freq: D, Timezone: None
[Finished in 1.1s]

  • 频率和日期偏移量

有些频率所描述的时间点并不是均匀分隔的。例如'M'和'BM'就取决于每月的天数,对于后者,还要考虑月末是不是周末,将这些成为锚点偏移量(anchored offset)。pandas还允许自定义一些日期逻辑,但是暂且不表。

#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas import Series,DataFrame
from datetime import datetime
from dateutil.parser import parse
import time
from pandas.tseries.offsets import Hour,Minute#pandas中的频率是由一个基础频率和一个乘数组成的。基础的频率由字符串表示,比如‘M’表示月,‘H’表示小时
#对于每个基础频率,都有一个被称为日期偏移量(date offset)的对象与之对应。
hour = Hour()
print hour #感觉这个形式比较霸气
#传入整数可以自定义偏移量倍数
four_hours = Hour(4)
print four_hours
#一般而言,并不需要显示创建偏移量,只需创建时间序列时传入'H'或者'4h'即可
print pd.date_range('1/1/2016','1/2/2016',freq = '4h'),'\n'
#偏移量可以拼接
print Hour(1) + Minute(30)
#传入频率字符串('2h30min'),这种字符串可以被高效地解析为等效的表达式
print pd.date_range('1/1/2016',periods = 10,freq = '1h30min'),'\n'
#有些频率所描述的时间点并不是均匀分隔的。例如'M'和'BM'就取决于每月的天数,对于后者,还要考虑月末是不是周末,将这些成为锚点偏移量(anchored offset)
#WOM(Week Of Month)日期是一个非常常用的频率,以WOM开头,能产生诸如“每月第三个星期五”之类的信息
rng = pd.date_range('1/1/2016','9/1/2016',freq = 'WOM-3FRI')
print rng
>>>
<1 Hour><4 Hours><class 'pandas.tseries.index.DatetimeIndex'>[2016-01-01 00:00:00, ..., 2016-01-02 00:00:00]Length: 7, Freq: 4H, Timezone: None 

<90 Minutes>
<class 'pandas.tseries.index.DatetimeIndex'>
[2016-01-01 00:00:00, ..., 2016-01-01 13:30:00]
Length: 10, Freq: 90T, Timezone: None

<class 'pandas.tseries.index.DatetimeIndex'>
[2016-01-15 00:00:00, ..., 2016-08-19 00:00:00]
Length: 8, Freq: WOM-3FRI, Timezone: None
[Finished in 1.1s]

下面是一些常用的基础频率,很多很详细。


  • 移动(超前和滞后)数据

移动(shifting)指的是沿着时间轴将数据前移或后移。Series和DataFrame都有一个shift方法用于执行单纯的前移或后移操作,保持索引不变。

#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas import Series,DataFrame
from datetime import datetime
from dateutil.parser import parse
import time
from pandas.tseries.offsets import Hour,Minutets = Series(np.random.randn(4),index = pd.date_range('1/1/2016',periods = 4,freq = 'M'))
print ts
print ts.shift(2)
print ts.shift(-2),'\n'
#可以看到,shift通常用于计算一个时间序列或多个时间序列(如DataFrame列)中的百分比变化。
print ts / ts.shift(1) - 1
#单纯的移位操作不会修改索引,所以部分数据会被丢弃,如果频率已知,则可以将其传给shift以实现对时间戳进行位移而不是只对数据移位
print ts.shift(2,freq = 'M')  #时间戳移动,而数据不动
#当然也可以自己定义移动的频率
print ts.shift(3,freq = 'D'),'\n'  #时间的移动不是上下移动,而是将时间列的每个值进行移动
print ts.shift(1,freq = '3D')
print ts.shift(1,freq = '90T')
>>>
2016-01-31    0.7214452016-02-29   -0.5682002016-03-31   -0.9452882016-04-30    0.198176Freq: M2016-01-31         NaN2016-02-29         NaN2016-03-31    0.7214452016-04-30   -0.568200Freq: M2016-01-31   -0.9452882016-02-29    0.1981762016-03-31         NaN2016-04-30         NaNFreq: M 

2016-01-31         NaN
2016-02-29   -1.787585
2016-03-31    0.663653
2016-04-30   -1.209646
Freq: M
2016-03-31    0.721445
2016-04-30   -0.568200
2016-05-31   -0.945288
2016-06-30    0.198176
Freq: M
2016-02-03    0.721445
2016-03-03   -0.568200
2016-04-03   -0.945288
2016-05-03    0.198176

2016-02-03    0.721445
2016-03-03   -0.568200
2016-04-03   -0.945288
2016-05-03    0.198176
2016-01-31 01:30:00    0.721445
2016-02-29 01:30:00   -0.568200
2016-03-31 01:30:00   -0.945288
2016-04-30 01:30:00    0.198176
[Finished in 0.7s]

  • 通过偏移量对日期进行位移

pandas的日期偏移量还可以用在datetime或Timestemp对象上。

#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas import Series,DataFrame
from datetime import datetime
from dateutil.parser import parse
import time
from pandas.tseries.offsets import Hour,Minute,Day,MonthEndnow = datetime(2011,11,29)
print type(now)
print now + Day(3),'\n'
#如果加的是锚点偏移量,第一次增量会将原日期向前滚动到符合频率规则的下一个日期
#如果本来就是锚点,那么下一个就是下一个锚点
print now + MonthEnd(),'\n'
print now + MonthEnd(2),'\n'
#通过锚点偏移量的rollforward和rollback方法,可显示地将日期向前或向后“滚动”
offset = MonthEnd()
print offset.rollforward(now),'\n'
print offset.rollback(now),'\n'
#日期偏移量还有一个巧妙的用法,即结合groupby使用这两个“滚动”方法
ts = Series(np.random.randn(20),index = pd.date_range('1/15/2000',periods = 20,freq = '4d'))
print ts,'\n'
#注意下面的方式,很隐晦
print ts.groupby(offset.rollforward).mean(),'\n'
#当然,更简单快速的方式是使用resample
print ts.resample('M',how = 'mean')
>>>
<type 'datetime.datetime'>2011-12-02 00:00:00 
2011-11-30 00:00:00 
2011-12-31 00:00:00 
2011-11-30 00:00:00 
2011-10-31 00:00:00 
2000-01-15   -1.2342842000-01-19   -1.0786412000-01-23   -0.7272572000-01-27   -0.9437982000-01-31    0.0505862000-02-04    0.0198332000-02-08   -1.4072442000-02-12   -0.4464142000-02-16   -0.5218472000-02-20    0.0662002000-02-24    1.6045802000-02-28   -0.7147622000-03-03    1.7434592000-03-07    1.6753882000-03-11    0.1047012000-03-15    0.1245332000-03-19   -1.1133062000-03-23   -1.4429062000-03-27   -0.4898182000-03-31    0.344161Freq: 4D 
2000-01-31   -0.7866792000-02-29   -0.1999502000-03-31    0.118276 
 
2000-01-31   -0.7866792000-02-29   -0.1999502000-03-31    0.118276Freq: M[Finished in 0.7s]

4、时区处理

时间序列最让人不爽的就是对时区的处理。很多人已经用协调世界时(UTC,格林尼治时间接替者,目前是国际标准)来处理时间序列。时区就是以UTC偏移量的形式表示的。

Python中,时区信息来自第三方库pytz,它可以使Python可以使用Olson数据库。pandas包装了pytz功能。因此不用记忆API,只要记得时区名称即可。时区名可以在文档中找到。

#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas import Series,DataFrame
from datetime import datetime
from dateutil.parser import parse
import time
from pandas.tseries.offsets import Hour,Minute,Day,MonthEnd
import pytzprint pytz.common_timezones[-5:]
#要从pytz中获取时区对象,使用pytz.timezone即可
tz = pytz.timezone('US/Eastern')
print tz #这里的输出已经和课本上不一样,估计是进行了简化,使得更方便了
>>>
['US/Eastern', 'US/Hawaii', 'US/Mountain', 'US/Pacific', 'UTC']US/Eastern[Finished in 0.7s]

  • 本地化和转换

默认情况下,pandas中的序列是单纯的(naive[too young too simple!navie!])时区。

#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas import Series,DataFrame
from datetime import datetime
from dateutil.parser import parse
import time
from pandas.tseries.offsets import Hour,Minute,Day,MonthEnd
import pytzrng = pd.date_range('3/9/2012 9:30',periods = 6,freq = 'D')
ts = Series(np.random.randn(len(rng)),index = rng)
print ts,'\n'
print ts.index.tz,'\n'  #默认的时区字段为None
#在生成日期范围的时候还可以加上一个时区集
print pd.date_range('3/9/2012',periods = 10,freq = 'D',tz = 'UTC'),'\n'
#从单纯到本地化的转换是通过tz_localize方法处理的:
ts_utc = ts.tz_localize('US/Pacific')  #转换为美国太平洋时间
print ts_utc,'\n'
print ts_utc.index,'\n'
#一旦被转换为某个特定时期,就可以用tz_convert将其转换到其他时区了
print ts_utc.tz_convert('US/Eastern'),'\n'
#tz_localize和tz_convert是DatetimeIndex的实例方法,可以把一个DatetimeIndex转化为特定时区
print ts.index.tz_localize('Asia/Shanghai')
>>>
2012-03-09 09:30:00    0.0795302012-03-10 09:30:00   -0.4344502012-03-11 09:30:00    0.3607392012-03-12 09:30:00    0.6780652012-03-13 09:30:00   -0.7053742012-03-14 09:30:00    0.684572Freq: D 

None

<class 'pandas.tseries.index.DatetimeIndex'>
[2012-03-09 00:00:00, ..., 2012-03-18 00:00:00]
Length: 10, Freq: D, Timezone: UTC

2012-03-09 09:30:00-08:00    0.079530
2012-03-10 09:30:00-08:00   -0.434450
2012-03-11 09:30:00-07:00    0.360739
2012-03-12 09:30:00-07:00    0.678065
2012-03-13 09:30:00-07:00   -0.705374
2012-03-14 09:30:00-07:00    0.684572
Freq: D

<class 'pandas.tseries.index.DatetimeIndex'>
[2012-03-09 09:30:00, ..., 2012-03-14 09:30:00]
Length: 6, Freq: D, Timezone: US/Pacific

2012-03-09 12:30:00-05:00    0.079530
2012-03-10 12:30:00-05:00   -0.434450
2012-03-11 12:30:00-04:00    0.360739
2012-03-12 12:30:00-04:00    0.678065
2012-03-13 12:30:00-04:00   -0.705374
2012-03-14 12:30:00-04:00    0.684572
Freq: D

<class 'pandas.tseries.index.DatetimeIndex'>
[2012-03-09 09:30:00, ..., 2012-03-14 09:30:00]
Length: 6, Freq: D, Timezone: Asia/Shanghai
[Finished in 0.6s]

  • 操作时区意识型(time zone-aware)Timestamp对象

跟时间序列和日期序列差不多,Timestamp对象也能被从单纯型(navie)本地化为time zone-aware,并从一个时区转换为另一个时区。

#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas import Series,DataFrame
from datetime import datetime
from dateutil.parser import parse
import time
from pandas.tseries.offsets import Hour,Minute,Day,MonthEnd
import pytzstamp = pd.Timestamp('2011-03-12 04:00')
print type(stamp),'\n'
stamp_utc = stamp.tz_localize('UTC')
print stamp_utc,'\n'
print stamp_utc.tz_convert('US/Eastern'),'\n'
stamp_moscow = pd.Timestamp('2011-03-12 04:00',tz = 'Europe/Moscow')
print stamp_moscow
#时区意识型Timestamp对象在内部保存了一个UTC时间戳值(自1970年1月1日起的纳秒数),这个UTC值在时区转换过程中是不会变化的
print stamp_utc.value
print stamp_utc.tz_convert('US/Eastern').value,'\n'
#当使用pandas的DataOffset对象执行运算时,会自动关注“夏时令”…………
>>>

<class 'pandas.lib.Timestamp'>

2011-03-12 04:00:00+00:00

2011-03-11 23:00:00-05:00

2011-03-12 04:00:00+03:00
1299902400000000000
1299902400000000000
[Finished in 0.7s]

  • 不同时区之间的运算

如果时间时间时区不同,那么结果就会是UTC时间,由于时间戳其实是以UTC储存的,索引计算很方便。

#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas import Series,DataFrame
from datetime import datetime
from dateutil.parser import parse
import time
from pandas.tseries.offsets import Hour,Minute,Day,MonthEnd
import pytzrng = pd.date_range('3/7/2012',periods = 10,freq = 'B')
ts = Series(np.random.randn(len(rng)),index = rng)
print ts
ts1 = ts[:7].tz_localize('Europe/London')
#注意naive是不能直接转换为时区的,必须先转换为localize再进行转换
ts2 = ts1[2:].tz_convert('Europe/Moscow')
result = ts1 + ts2
#转换为UTC
print result.index
>>>
2012-03-07   -0.5914172012-03-08    1.0096512012-03-09   -1.9220042012-03-12    0.2462062012-03-13    0.0334302012-03-14    0.6149112012-03-15    1.9440142012-03-16   -2.3498462012-03-19    0.4259252012-03-20    1.941166Freq: B<class 'pandas.tseries.index.DatetimeIndex'>[2012-03-07 00:00:00, ..., 2012-03-15 00:00:00]Length: 7, Freq: B, Timezone: UTC[Finished in 0.7s]

转载于:https://www.cnblogs.com/batteryhp/p/5055149.html

《利用python进行数据分析》读书笔记--第十章 时间序列(一)相关推荐

  1. 《利用Python进行数据分析》笔记--NumPy数组和矢量计算

    阅读SeanCheney博主上传的文章有感,特此写一篇笔记,如侵必删. 第四章 NumPy基础 NumPy的ndarray:一种多维数组对象 1. 创建ndarray array函数,接受序列性的对象 ...

  2. 利用Python进行数据分析 学习笔记

    import os os.getcwd() 获得工作目录, 如使用相对路径,是相对于这个工作目录的路劲 import sys sys.path.append() 这个是增加引用,或引入文件的路径 In ...

  3. 《利用python进行数据分析》读书笔记--第十章 时间序列(二)

    5.时期及其算数运算 时期(period)表示的是时间区间,比如数日.数月.数季.数年等.Period类所表示的就是这种数据类型,其构造函数需要用到一个字符串或整数,以及频率. #-*- coding ...

  4. 《利用Python进行数据分析》笔记记录第六章——数据载入、存储及文件格式

    文章目录 前言 一.文本格式数据的读写 1.1 分块读入文件文本 1.2 将数据写入文件格式 1.3 使用分隔格式 1.4 JSON数据 1.5 XML和HTML:网络抓取 总结 前言 在上几篇文章中 ...

  5. 《利用Python进行数据分析》笔记---第6章数据加载、存储与文件格式

    写在前面的话: 实例中的所有数据都是在GitHub上下载的,打包下载即可. 地址是:http://github.com/pydata/pydata-book 还有一定要说明的: 我使用的是Python ...

  6. 《利用Python进行数据分析》笔记---第8章绘图和可视化

    写在前面的话: 实例中的所有数据都是在GitHub上下载的,打包下载即可. 地址是:http://github.com/pydata/pydata-book 还有一定要说明的: 我使用的是Python ...

  7. 用python进行数据分析举例说明_《利用python进行数据分析》读书笔记 --第一、二章 准备与例子...

    第一章 准备工作 今天开始码这本书--<利用python进行数据分析>.R和python都得会用才行,这是码这本书的原因.首先按照书上说的进行安装,google下载了epd_free-7. ...

  8. 《利用python进行数据分析》读书笔记

    <利用python进行数据分析>是一本利用python的Numpy.Pandas.Matplotlib库进行数据分析的基础介绍,非常适合初学者. 重要的python库 NumPy http ...

  9. 学完可以解决90%以上的数据分析问题-利用python进行数据分析第二版(代码和中文笔记)...

    <利用python进行数据分析>是数据分析的基础教程,绝大部分数据分析师的入门教材,目前已经升级到第二版.本站搜集了教材的第二版原版代码进行中文翻译和注释,并做了一定的笔记.基本上只需要看 ...

最新文章

  1. GeoPandas 笔记: GeoDataFrame.plot()
  2. Spring —— 容器内部逻辑
  3. 解读程序员的武侠世界,顶级程序员是内外兼修的大侠,那么你呢?
  4. mysql中merge的用法_mysql中merge表存儲引擎用法介紹
  5. java asm源码分析_探究CAS原理(基于JAVA8源码分析)
  6. Dorado Debugger工具
  7. postgre数据库下的 NOT NULL 和 空串(虽然有NOT NULL设定,但是可以插入空串'')
  8. java 删除list_Java 删除List元素的正确方式
  9. AcWing 858. Prim算法求最小生成树(稠密图)
  10. 最简洁的PHP把PHP生成HTML代码
  11. 有关使用seajs和template模板的总结
  12. 微信小程序css方式animation动画弹幕实现
  13. linux环境安装的odac,net不安装Oracle11g客户端直接使用ODAC
  14. 怎样删除计算机Windows7自带的游戏,win7自带游戏如何卸载?win7卸载自带游戏的步骤...
  15. EXCEL的去重去除某个字段后全部操作
  16. e.keycode 代码含义
  17. outlook如何同步服务器sent文件夹,.ost 文件的同步问题 - Exchange | Microsoft Docs
  18. 关于eslint误报Unexpected side effect in “getCheckedData“ computed property的问题
  19. Shell语法详解专栏目录
  20. 想做副业怎么才能找到适合的项目,六条建议让你找副业不再迷茫

热门文章

  1. 树:哈夫曼树和哈夫曼编码的详细介绍以及代码实现
  2. Git HEAD detached from XXX (git HEAD 游离) 解决办法
  3. bzoj1612 Usaco08 Jan 牛大赛
  4. linux主机名的修改
  5. ubuntu 中怎么安装 jdk 7
  6. 《101 Windows Phone 7 Apps》读书笔记-BABY MILESTONES
  7. Nocatalog 下的RMAN 增量备份 shell脚本
  8. 普通码农和技术大牛之间,只差这10本书(1024高能福利)
  9. Linux系统里如何重装ibus,Linux下安装ibus-rime的方法
  10. 假如王撕葱是程序员。。。