利用python进行数据分析-时间序列2
2016-08-06 21:11
846 查看
1.带有重复索引的时间序列
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
结果为:
2000-01-01 0
2000-01-02 1
2000-01-02 2
2000-01-02 3
2000-01-03 4
dtype: int32
通过检查索引的is_unique属性,我们就可以知道它是不是唯一的
print dup_ts.index.is_unique
结果为:
False
对这个时间序列进行索引,要么产生标量值,要么产生切片,具体要看所选的时间点是否重复
print dup_ts['1/3/2000'] #不重复
print dup_ts['1/2/2000'] #重复
结果为:
4
2000-01-02 1
2000-01-02 2
2000-01-02 3
dtype: int32
假设你想要对具有唯一时间戳的数据进行聚合。一个办法是使用groupby,并传入level=0(索引的唯一 一层!)
grouped=dup_ts.groupby(level=0)
print grouped.mean()
print grouped.count()
结果为:
2000-01-01 0
2000-01-02 2
2000-01-03 4
dtype: int32
2000-01-01 1
2000-01-02 3
2000-01-03 1
dtype: int64
2.日期的范围、频率以及移动
dates=[datetime.datetime(2011,1,2),datetime.datetime(2011,1,5),
datetime.datetime(2011,1,7),datetime.datetime(2011,1,8),
datetime.datetime(2011,1,10),datetime.datetime(2011,1,12)]
ts=Series(np.random.randn(6),index=dates)
print ts
print ts.resample('D')
结果为:
2011-01-02 1.068995
2011-01-05 0.564281
2011-01-07 1.910822
2011-01-08 -0.339067
2011-01-10 -1.671388
2011-01-12 -0.679710
dtype: float64
2011-01-02 1.068995
2011-01-03 NaN
2011-01-04 NaN
2011-01-05 0.564281
2011-01-06 NaN
2011-01-07 1.910822
2011-01-08 -0.339067
2011-01-09 NaN
2011-01-10 -1.671388
2011-01-11 NaN
2011-01-12 -0.679710
Freq: D, dtype: float64
3.生成日期范围
index=pd.date_range('4/1/2012','6/1/2012')
print index
结果为:
DatetimeIndex(['2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04',
'2012-04-05', '2012-04-06', '2012-04-07', '2012-04-08',
'2012-04-09', '2012-04-10', '2012-04-11', '2012-04-12',
'2012-04-13', '2012-04-14', '2012-04-15', '2012-04-16',
'2012-04-17', '2012-04-18', '2012-04-19', '2012-04-20',
'2012-04-21', '2012-04-22', '2012-04-23', '2012-04-24',
'2012-04-25', '2012-04-26', '2012-04-27', '2012-04-28',
'2012-04-29', '2012-04-30', '2012-05-01', '2012-05-02',
'2012-05-03', '2012-05-04', '2012-05-05', '2012-05-06',
'2012-05-07', '2012-05-08', '2012-05-09', '2012-05-10',
'2012-05-11', '2012-05-12', '2012-05-13', '2012-05-14',
'2012-05-15', '2012-05-16', '2012-05-17', '2012-05-18',
'2012-05-19', '2012-05-20', '2012-05-21', '2012-05-22',
'2012-05-23', '2012-05-24', '2012-05-25', '2012-05-26',
'2012-05-27', '2012-05-28', '2012-05-29', '2012-05-30',
'2012-05-31', '2012-06-01'],
dtype='datetime64[ns]', freq='D')
默认情况下,date_range会产生按天计算的时间点。如果只传入起始或结束日期,那就还得传入一个表示一段时间的数字
print pd.date_range(start='4/1/2012',periods=20)
print pd.date_range(end='6/1/2012',periods=20)
结果为:
DatetimeIndex(['2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04',
'2012-04-05', '2012-04-06', '2012-04-07', '2012-04-08',
'2012-04-09', '2012-04-10', '2012-04-11', '2012-04-12',
'2012-04-13', '2012-04-14', '2012-04-15', '2012-04-16',
'2012-04-17', '2012-04-18', '2012-04-19', '2012-04-20'],
dtype='datetime64[ns]', freq='D')
DatetimeIndex(['2012-05-13', '2012-05-14', '2012-05-15', '2012-05-16',
'2012-05-17', '2012-05-18', '2012-05-19', '2012-05-20',
'2012-05-21', '2012-05-22', '2012-05-23', '2012-05-24',
'2012-05-25', '2012-05-26', '2012-05-27', '2012-05-28',
'2012-05-29', '2012-05-30', '2012-05-31', '2012-06-01'],
dtype='datetime64[ns]', freq='D')
起始和结束日期定义了日期索引的严格边界。如果你想生成一个由每月最后一个工作日组成的日期索引,可以传入“BM”频率,这样只会包含时间间隔内符合频率要求的日期
print pd.date_range('1/1/2000','12/1/2000',freq='BM')
结果为:
DatetimeIndex(['2000-01-31', '2000-02-29', '2000-03-31', '2000-04-28',
'2000-05-31', '2000-06-30', '2000-07-31', '2000-08-31',
'2000-09-29', '2000-10-31', '2000-11-30'],
dtype='datetime64[ns]', freq='BM')
有时,虽然起始和结束日期带有时间信息,但你希望产生一组规范化到午夜的时间戳。normalize选项即可实现该功能
print pd.date_range('5/2/2012 12:56:31',periods=5,normalize=True)
结果为:
DatetimeIndex(['2012-05-02', '2012-05-03', '2012-05-04', '2012-05-05',
'2012-05-06'],
dtype='datetime64[ns]', freq='D')
4.频率和日期偏移量
pandas中的频率是由一个基础频率和一个乘数组成的。基础频率通常以一个字符串别名表示,比如“M”表示每月,“H”表示每小时。对于每个基础频率,都有一个被称为日期偏移量的对象与之对应。例如,按小时计算的频率可以用Hour类表示
from pandas.tseries.offsets import Hour,Minute
hour=Hour()
print hour
结果为:
<Hour>
传入一个整数即可定义偏移量的倍数
four_hours=Hour(4)
print four_hours
结果为:
<4 * Hours>
一般来说,无需显示创建这样的对象,只需使用诸如“H”或“4H”这样的字符串别名即可。在基础频率前面放上一个整数即可创建倍数
print pd.date_range('1/1/2000','1/3/2000 23:59',freq='4h')
结果为:
DatetimeIndex(['2000-01-01 00:00:00', '2000-01-01 04:00:00',
'2000-01-01 08:00:00', '2000-01-01 12:00:00',
'2000-01-01 16:00:00', '2000-01-01 20:00:00',
'2000-01-02 00:00:00', '2000-01-02 04:00:00',
'2000-01-02 08:00:00', '2000-01-02 12:00:00',
'2000-01-02 16:00:00', '2000-01-02 20:00:00',
'2000-01-03 00:00:00', '2000-01-03 04:00:00',
'2000-01-03 08:00:00', '2000-01-03 12:00:00',
'2000-01-03 16:00:00', '2000-01-03 20:00:00'],
dtype='datetime64[ns]', freq='4H')
大部分偏移量对象都可通过加法进行连接
print Hour(2)+Minute(30)
结果为:
<150 * Minutes>
同理,你也可以传入频率字符串,这种字符串可以被高效地解析为等效的表达式
print pd.date_range('1/1/2000',periods=10,freq='1h30min')
结果为:
<150 * Minutes>
DatetimeIndex(['2000-01-01 00:00:00', '2000-01-01 01:30:00',
'2000-01-01 03:00:00', '2000-01-01 04:30:00',
'2000-01-01 06:00:00', '2000-01-01 07:30:00',
'2000-01-01 09:00:00', '2000-01-01 10:30:00',
'2000-01-01 12:00:00', '2000-01-01 13:30:00'],
dtype='datetime64[ns]', freq='90T')
有些频率所描述的时间点并不是均匀分隔的。例如,“M”(日历月末)和“BM”(每月最后一个工作日)就取决于每月的天数。由于没有更好的术语,我将这些称为锚点偏移量
![](http://img.blog.csdn.net/20160806142901566?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20160806142921925?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20160806142937066?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
5.WOM日期
WOM能获得诸如“每月第3个星期五”之类的日期
rng=pd.date_range('1/1/2012','9/1/2012',freq='WOM-3FRI')
print list(rng)
结果为:
[Timestamp('2012-01-20 00:00:00', offset='WOM-3FRI'), Timestamp('2012-02-17 00:00:00', offset='WOM-3FRI'), Timestamp('2012-03-16 00:00:00', offset='WOM-3FRI'), Timestamp('2012-04-20 00:00:00', offset='WOM-3FRI'), Timestamp('2012-05-18
00:00:00', offset='WOM-3FRI'), Timestamp('2012-06-15 00:00:00', offset='WOM-3FRI'), Timestamp('2012-07-20 00:00:00', offset='WOM-3FRI'), Timestamp('2012-08-17 00:00:00', offset='WOM-3FRI')]
6.移动(超前和滞后)数据
移动指的是沿着时间轴将数据前移或后移。Series和DataFrame都有一个shift方法用于执行单纯的前移或后移操作,保持索引不变
ts=Series(np.random.randn(4),index=pd.date_range('1/1/2000',periods=4,freq='M'))
print ts
print ts.shift(2)
print ts.shift(-2)
结果为:
2000-01-31 -0.389670
2000-02-29 0.541153
2000-03-31 0.998715
2000-04-30 -0.800795
Freq: M, dtype: float64
2000-01-31 NaN
2000-02-29 NaN
2000-03-31 -0.389670
2000-04-30 0.541153
Freq: M, dtype: float64
2000-01-31 0.998715
2000-02-29 -0.800795
2000-03-31 NaN
2000-04-30 NaN
Freq: M, dtype: float64
shift通常用于计算一个时间序列或多个时间序列中的百分比变化,可以这样表达:ts/ts.shift(1)-1
由于单纯的移位操作不会修改索引,所以部分数据会被丢弃。如果频率已知,则可以将其传给shift以便实现对时间戳进行位移而不是对数据进行简单位移
print ts.shift(2,freq='M')
结果为:
2000-03-31 -0.355693
2000-04-30 0.708167
2000-05-31 0.870448
2000-06-30 -0.804584
Freq: M, dtype: float64
这里还可以使用其他频率
print ts.shift(3,freq='D')
print ts.shift(1,freq='3D')
print ts.shift(1,freq='90T')
结果为:
2000-02-03 -1.045612
2000-03-03 2.034699
2000-04-03 -0.189753
2000-05-03 -0.314928
dtype: float64
2000-02-03 -1.045612
2000-03-03 2.034699
2000-04-03 -0.189753
2000-05-03 -0.314928
dtype: float64
2000-01-31 01:30:00 -1.045612
2000-02-29 01:30:00 2.034699
2000-03-31 01:30:00 -0.189753
2000-04-30 01:30:00 -0.314928
Freq: M, dtype: float64
7.通过偏移量对日期进行位移
pandas的日期偏移量还可以用在datetime或Timestamp对象上
from pandas.tseries.offsets import Day,MonthEnd
now=datetime.datetime(2011,11,17)
print now+3*Day()
结果为:
2011-11-20 00:00:00
如果加的是锚点偏移量,第一次增重会将原日期向前滚动到符合频率规则的下一个日期
print now+MonthEnd()
print now+MonthEnd(2)
结果为:
2011-11-30 00:00:00
2011-12-31 00:00:00
通过锚点偏移量的rollforward和rollback方法,可显式地将日期向前或向后“滚动”
offset=MonthEnd()
print offset.rollforward(now)
print offset.rollback(now)
结果为:
2011-11-30 00:00:00
2011-10-31 00:00:00
日期偏移量还有一个巧妙的用法,即结合groupby使用这两个滚动方法
ts=Series(np.random.randn(20),index=pd.date_range('1/15/2000',periods=20,freq='4d'))
print ts.groupby(offset.rollforward).mean()
结果为:
2000-01-31 -0.024235
2000-02-29 -0.182988
2000-03-31 -0.458176
dtype: float64
更简单、更快速地是实现该功能的办法是使用resample
print ts.resample('M',how='mean')
结果为:
2000-01-31 -0.076951
2000-02-29 -0.093232
2000-03-31 -0.390766
Freq: M, dtype: float64
8.时区处理
时区名可以在文档中找到,也可以通过交互的方式查看
import pytz
print pytz.common_timezones[-5:]
结果为:
['US/Eastern', 'US/Hawaii', 'US/Mountain', 'US/Pacific', 'UTC']
要从pytz中获取时区对象,使用pytz.timezone即可
tz=pytz.timezone('US/Eastern')
print tz
结果为:
US/Eastern
9.本地化和转换
默认情况下,pandas中的时间序列是单纯的时区。看看下面这个时间序列
rng=pd.date_range('3/9/2012 9:30',periods=6,freq='D')
ts=Series(np.random.rand(len(rng)),index=rng)
其索引的tz字段为None
print ts.index.tz
结果为:
None
在生成日期范围的时候还可以加上一个时区集
print pd.date_range('3/9/2012 9:30',periods=10,freq='D',tz='UTC')
结果为:
DatetimeIndex(['2012-03-09 09:30:00+00:00', '2012-03-10 09:30:00+00:00',
'2012-03-11 09:30:00+00:00', '2012-03-12 09:30:00+00:00',
'2012-03-13 09:30:00+00:00', '2012-03-14 09:30:00+00:00',
'2012-03-15 09:30:00+00:00', '2012-03-16 09:30:00+00:00',
'2012-03-17 09:30:00+00:00', '2012-03-18 09:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq='D')
从单纯到本地化的转换是通过tz_localize方法处理的
ts_utc=ts.tz_localize('UTC')
print ts_utc
结果为:
2012-03-09 09:30:00+00:00 0.641279
2012-03-10 09:30:00+00:00 0.275813
2012-03-11 09:30:00+00:00 0.113782
2012-03-12 09:30:00+00:00 0.073940
2012-03-13 09:30:00+00:00 0.087528
2012-03-14 09:30:00+00:00 0.458625
Freq: D, dtype: float64
print ts_utc.index
结果为:
DatetimeIndex(['2012-03-09 09:30:00+00:00', '2012-03-10 09:30:00+00:00',
'2012-03-11 09:30:00+00:00', '2012-03-12 09:30:00+00:00',
'2012-03-13 09:30:00+00:00', '2012-03-14 09:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq='D')
一旦时间序列被本地化到某个特定时区,就可以用tz_convert将其转换到别的时区了
print ts_utc.tz_convert('US/Eastern')
结果为:
2012-03-09 04:30:00-05:00 0.595619
2012-03-10 04:30:00-05:00 0.337900
2012-03-11 05:30:00-04:00 0.552080
2012-03-12 05:30:00-04:00 0.922716
2012-03-13 05:30:00-04:00 0.311070
2012-03-14 05:30:00-04:00 0.682581
Freq: D, dtype: float64
对于上面这种时间序列(它跨越了美国东部时区的夏令时转变期),我们可以将其本地化到EST,然后转换为UTC或柏林时间
ts_eastern=ts.tz_localize('US/Eastern')
print ts_eastern.tz_convert('UTC')
结果为:
2012-03-09 14:30:00+00:00 0.696696
2012-03-10 14:30:00+00:00 0.798250
2012-03-11 13:30:00+00:00 0.237720
2012-03-12 13:30:00+00:00 0.826396
2012-03-13 13:30:00+00:00 0.304436
2012-03-14 13:30:00+00:00 0.162294
Freq: D, dtype: float64
print ts_eastern.tz_convert('Europe/Berlin')
结果为:
2012-03-09 15:30:00+01:00 0.116943
2012-03-10 15:30:00+01:00 0.805555
2012-03-11 14:30:00+01:00 0.765655
2012-03-12 14:30:00+01:00 0.762651
2012-03-13 14:30:00+01:00 0.947182
2012-03-14 14:30:00+01:00 0.670358
Freq: D, dtype: float64
tz_localize和tz_convert也是DatatimeIndex的实例方法
结果为:
print 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')
10.操作时区意识型Timestamp对象
跟时间序列和日期范围差不多,Timestamp对象也能从单纯型本地化为时区意识型,并从一个时区转换到另一个时区
stamp=pd.Timestamp('2011-03-12 04:00')
stamp_utc=stamp.tz_localize('utc')
print stamp_utc.tz_convert('US/Eastern')
结果为:
2011-03-11 23:00:00-05:00
在创建Timestamp时,还可以传入一个时区信息
stamp_moscow=pd.Timestamp('2011-03-12 04:00',tz='Europe/Moscow')
print stamp_moscow
结果为:
2011-03-12 04:00:00+03:00
时区意识型Timestamp对象在内部保存了一个UTC时间戳值。这个UTC值在时区转换过程中是不会发生变化的
print stamp_utc.value
print stamp_utc.tz_convert('US/Eastern').value
结果为:
1299902400000000000
1299902400000000000
当使用pandas的DateOffset对象执行时间算术运算时,运算过程中会自动关注是否存在夏令时转变期
from pandas.tseries.offsets import Hour
#夏令时转变前30分钟
stamp=pd.Timestamp('2012-03-12 01:30',tz='US/Eastern')
print stamp
print stamp+Hour()
#夏令时转变前90分钟
stamp=pd.Timestamp('2012-11-04 00:30',tz='US/Eastern')
print stamp
print stamp+2*Hour()
结果为:
2012-03-12 01:30:00-04:00
2012-03-12 02:30:00-04:00
2012-11-04 00:30:00-04:00
2012-11-04 01:30:00-05:00
11.不同时区之间的运算
如果两个时间序列的时区不同,在将它们合并到一起时,最终结果就会是UTC。由于时间戳其实是你UTC存储的,所以这是一个很简单的运算,并不需要发生任何转换
rng=pd.date_range('3/7/2012 09:30',periods=10,freq='B')
ts=Series(np.random.randn(len(rng)),index=rng)
print ts
结果为:
2012-03-07 09:30:00 1.533603
2012-03-08 09:30:00 -0.224899
2012-03-09 09:30:00 0.542026
2012-03-12 09:30:00 -0.815753
2012-03-13 09:30:00 -1.421795
2012-03-14 09:30:00 0.399534
2012-03-15 09:30:00 0.293016
2012-03-16 09:30:00 -1.612594
2012-03-19 09:30:00 0.072332
2012-03-20 09:30:00 0.313340
Freq: B, dtype: float64
ts1=ts[:7].tz_localize('Europe/London')
ts2=ts1[2:].tz_convert('Europe/Moscow')
result=ts1+ts2
print result.index
结果为:
DatetimeIndex(['2012-03-07 09:30:00+00:00', '2012-03-08 09:30:00+00:00',
'2012-03-09 09:30:00+00:00', '2012-03-12 09:30:00+00:00',
'2012-03-13 09:30:00+00:00', '2012-03-14 09:30:00+00:00',
'2012-03-15 09:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq='B')
12.日期及其算术运算
时期表示的是时间区间,比如数日、数月、数季、数年等。Period类所表示的就是这种数据类型,其构造函数需要用到一个字符串或整数,以及表中的频率
p=pd.Period(2007,freq='A-DEC')
print p
结果为:
2007
这个Period对象表示的是从2007年1月1日到2007年12月31日之间的整段时间。只需对Period对象加上或减去一个整数即可达到根据其频率进行位移的效果
print p+5
print p-2
结果为:
2012
2005
如果两个Period对象拥有相同的频率,则它们的差就是它们之间的单位数量
print pd.Period('2014',freq='A-DEC')-p
结果为:
7
period_range函数可用于创建规则的时期范围
rng=pd.date_range('1/1/2000','6/30/2000',freq='M')
print rng
结果为:
DatetimeIndex(['2000-01-31', '2000-02-29', '2000-03-31', '2000-04-30',
'2000-05-31', '2000-06-30'],
dtype='datetime64[ns]', freq='M')
PeriodIndex类保存了一组Period,它可以在任何pandas数据结构中被用做轴索引
print Series(np.random.randn(6),index=rng)
结果为:
2000-01-31 -1.375039
2000-02-29 -0.143529
2000-03-31 2.162475
2000-04-30 2.109093
2000-05-31 0.759747
2000-06-30 -1.994800
Freq: M, dtype: float64
PeriodIndex类的构造函数还允许直接使用一组字符串
values=['2001Q3','2002Q2','2003Q1']
index=pd.PeriodIndex(values,freq='Q-DEC')
print index
结果为:
PeriodIndex(['2001Q3', '2002Q2', '2003Q1'], dtype='int64', freq='Q-DEC')
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
结果为:
2000-01-01 0
2000-01-02 1
2000-01-02 2
2000-01-02 3
2000-01-03 4
dtype: int32
通过检查索引的is_unique属性,我们就可以知道它是不是唯一的
print dup_ts.index.is_unique
结果为:
False
对这个时间序列进行索引,要么产生标量值,要么产生切片,具体要看所选的时间点是否重复
print dup_ts['1/3/2000'] #不重复
print dup_ts['1/2/2000'] #重复
结果为:
4
2000-01-02 1
2000-01-02 2
2000-01-02 3
dtype: int32
假设你想要对具有唯一时间戳的数据进行聚合。一个办法是使用groupby,并传入level=0(索引的唯一 一层!)
grouped=dup_ts.groupby(level=0)
print grouped.mean()
print grouped.count()
结果为:
2000-01-01 0
2000-01-02 2
2000-01-03 4
dtype: int32
2000-01-01 1
2000-01-02 3
2000-01-03 1
dtype: int64
2.日期的范围、频率以及移动
dates=[datetime.datetime(2011,1,2),datetime.datetime(2011,1,5),
datetime.datetime(2011,1,7),datetime.datetime(2011,1,8),
datetime.datetime(2011,1,10),datetime.datetime(2011,1,12)]
ts=Series(np.random.randn(6),index=dates)
print ts
print ts.resample('D')
结果为:
2011-01-02 1.068995
2011-01-05 0.564281
2011-01-07 1.910822
2011-01-08 -0.339067
2011-01-10 -1.671388
2011-01-12 -0.679710
dtype: float64
2011-01-02 1.068995
2011-01-03 NaN
2011-01-04 NaN
2011-01-05 0.564281
2011-01-06 NaN
2011-01-07 1.910822
2011-01-08 -0.339067
2011-01-09 NaN
2011-01-10 -1.671388
2011-01-11 NaN
2011-01-12 -0.679710
Freq: D, dtype: float64
3.生成日期范围
index=pd.date_range('4/1/2012','6/1/2012')
print index
结果为:
DatetimeIndex(['2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04',
'2012-04-05', '2012-04-06', '2012-04-07', '2012-04-08',
'2012-04-09', '2012-04-10', '2012-04-11', '2012-04-12',
'2012-04-13', '2012-04-14', '2012-04-15', '2012-04-16',
'2012-04-17', '2012-04-18', '2012-04-19', '2012-04-20',
'2012-04-21', '2012-04-22', '2012-04-23', '2012-04-24',
'2012-04-25', '2012-04-26', '2012-04-27', '2012-04-28',
'2012-04-29', '2012-04-30', '2012-05-01', '2012-05-02',
'2012-05-03', '2012-05-04', '2012-05-05', '2012-05-06',
'2012-05-07', '2012-05-08', '2012-05-09', '2012-05-10',
'2012-05-11', '2012-05-12', '2012-05-13', '2012-05-14',
'2012-05-15', '2012-05-16', '2012-05-17', '2012-05-18',
'2012-05-19', '2012-05-20', '2012-05-21', '2012-05-22',
'2012-05-23', '2012-05-24', '2012-05-25', '2012-05-26',
'2012-05-27', '2012-05-28', '2012-05-29', '2012-05-30',
'2012-05-31', '2012-06-01'],
dtype='datetime64[ns]', freq='D')
默认情况下,date_range会产生按天计算的时间点。如果只传入起始或结束日期,那就还得传入一个表示一段时间的数字
print pd.date_range(start='4/1/2012',periods=20)
print pd.date_range(end='6/1/2012',periods=20)
结果为:
DatetimeIndex(['2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04',
'2012-04-05', '2012-04-06', '2012-04-07', '2012-04-08',
'2012-04-09', '2012-04-10', '2012-04-11', '2012-04-12',
'2012-04-13', '2012-04-14', '2012-04-15', '2012-04-16',
'2012-04-17', '2012-04-18', '2012-04-19', '2012-04-20'],
dtype='datetime64[ns]', freq='D')
DatetimeIndex(['2012-05-13', '2012-05-14', '2012-05-15', '2012-05-16',
'2012-05-17', '2012-05-18', '2012-05-19', '2012-05-20',
'2012-05-21', '2012-05-22', '2012-05-23', '2012-05-24',
'2012-05-25', '2012-05-26', '2012-05-27', '2012-05-28',
'2012-05-29', '2012-05-30', '2012-05-31', '2012-06-01'],
dtype='datetime64[ns]', freq='D')
起始和结束日期定义了日期索引的严格边界。如果你想生成一个由每月最后一个工作日组成的日期索引,可以传入“BM”频率,这样只会包含时间间隔内符合频率要求的日期
print pd.date_range('1/1/2000','12/1/2000',freq='BM')
结果为:
DatetimeIndex(['2000-01-31', '2000-02-29', '2000-03-31', '2000-04-28',
'2000-05-31', '2000-06-30', '2000-07-31', '2000-08-31',
'2000-09-29', '2000-10-31', '2000-11-30'],
dtype='datetime64[ns]', freq='BM')
有时,虽然起始和结束日期带有时间信息,但你希望产生一组规范化到午夜的时间戳。normalize选项即可实现该功能
print pd.date_range('5/2/2012 12:56:31',periods=5,normalize=True)
结果为:
DatetimeIndex(['2012-05-02', '2012-05-03', '2012-05-04', '2012-05-05',
'2012-05-06'],
dtype='datetime64[ns]', freq='D')
4.频率和日期偏移量
pandas中的频率是由一个基础频率和一个乘数组成的。基础频率通常以一个字符串别名表示,比如“M”表示每月,“H”表示每小时。对于每个基础频率,都有一个被称为日期偏移量的对象与之对应。例如,按小时计算的频率可以用Hour类表示
from pandas.tseries.offsets import Hour,Minute
hour=Hour()
print hour
结果为:
<Hour>
传入一个整数即可定义偏移量的倍数
four_hours=Hour(4)
print four_hours
结果为:
<4 * Hours>
一般来说,无需显示创建这样的对象,只需使用诸如“H”或“4H”这样的字符串别名即可。在基础频率前面放上一个整数即可创建倍数
print pd.date_range('1/1/2000','1/3/2000 23:59',freq='4h')
结果为:
DatetimeIndex(['2000-01-01 00:00:00', '2000-01-01 04:00:00',
'2000-01-01 08:00:00', '2000-01-01 12:00:00',
'2000-01-01 16:00:00', '2000-01-01 20:00:00',
'2000-01-02 00:00:00', '2000-01-02 04:00:00',
'2000-01-02 08:00:00', '2000-01-02 12:00:00',
'2000-01-02 16:00:00', '2000-01-02 20:00:00',
'2000-01-03 00:00:00', '2000-01-03 04:00:00',
'2000-01-03 08:00:00', '2000-01-03 12:00:00',
'2000-01-03 16:00:00', '2000-01-03 20:00:00'],
dtype='datetime64[ns]', freq='4H')
大部分偏移量对象都可通过加法进行连接
print Hour(2)+Minute(30)
结果为:
<150 * Minutes>
同理,你也可以传入频率字符串,这种字符串可以被高效地解析为等效的表达式
print pd.date_range('1/1/2000',periods=10,freq='1h30min')
结果为:
<150 * Minutes>
DatetimeIndex(['2000-01-01 00:00:00', '2000-01-01 01:30:00',
'2000-01-01 03:00:00', '2000-01-01 04:30:00',
'2000-01-01 06:00:00', '2000-01-01 07:30:00',
'2000-01-01 09:00:00', '2000-01-01 10:30:00',
'2000-01-01 12:00:00', '2000-01-01 13:30:00'],
dtype='datetime64[ns]', freq='90T')
有些频率所描述的时间点并不是均匀分隔的。例如,“M”(日历月末)和“BM”(每月最后一个工作日)就取决于每月的天数。由于没有更好的术语,我将这些称为锚点偏移量
5.WOM日期
WOM能获得诸如“每月第3个星期五”之类的日期
rng=pd.date_range('1/1/2012','9/1/2012',freq='WOM-3FRI')
print list(rng)
结果为:
[Timestamp('2012-01-20 00:00:00', offset='WOM-3FRI'), Timestamp('2012-02-17 00:00:00', offset='WOM-3FRI'), Timestamp('2012-03-16 00:00:00', offset='WOM-3FRI'), Timestamp('2012-04-20 00:00:00', offset='WOM-3FRI'), Timestamp('2012-05-18
00:00:00', offset='WOM-3FRI'), Timestamp('2012-06-15 00:00:00', offset='WOM-3FRI'), Timestamp('2012-07-20 00:00:00', offset='WOM-3FRI'), Timestamp('2012-08-17 00:00:00', offset='WOM-3FRI')]
6.移动(超前和滞后)数据
移动指的是沿着时间轴将数据前移或后移。Series和DataFrame都有一个shift方法用于执行单纯的前移或后移操作,保持索引不变
ts=Series(np.random.randn(4),index=pd.date_range('1/1/2000',periods=4,freq='M'))
print ts
print ts.shift(2)
print ts.shift(-2)
结果为:
2000-01-31 -0.389670
2000-02-29 0.541153
2000-03-31 0.998715
2000-04-30 -0.800795
Freq: M, dtype: float64
2000-01-31 NaN
2000-02-29 NaN
2000-03-31 -0.389670
2000-04-30 0.541153
Freq: M, dtype: float64
2000-01-31 0.998715
2000-02-29 -0.800795
2000-03-31 NaN
2000-04-30 NaN
Freq: M, dtype: float64
shift通常用于计算一个时间序列或多个时间序列中的百分比变化,可以这样表达:ts/ts.shift(1)-1
由于单纯的移位操作不会修改索引,所以部分数据会被丢弃。如果频率已知,则可以将其传给shift以便实现对时间戳进行位移而不是对数据进行简单位移
print ts.shift(2,freq='M')
结果为:
2000-03-31 -0.355693
2000-04-30 0.708167
2000-05-31 0.870448
2000-06-30 -0.804584
Freq: M, dtype: float64
这里还可以使用其他频率
print ts.shift(3,freq='D')
print ts.shift(1,freq='3D')
print ts.shift(1,freq='90T')
结果为:
2000-02-03 -1.045612
2000-03-03 2.034699
2000-04-03 -0.189753
2000-05-03 -0.314928
dtype: float64
2000-02-03 -1.045612
2000-03-03 2.034699
2000-04-03 -0.189753
2000-05-03 -0.314928
dtype: float64
2000-01-31 01:30:00 -1.045612
2000-02-29 01:30:00 2.034699
2000-03-31 01:30:00 -0.189753
2000-04-30 01:30:00 -0.314928
Freq: M, dtype: float64
7.通过偏移量对日期进行位移
pandas的日期偏移量还可以用在datetime或Timestamp对象上
from pandas.tseries.offsets import Day,MonthEnd
now=datetime.datetime(2011,11,17)
print now+3*Day()
结果为:
2011-11-20 00:00:00
如果加的是锚点偏移量,第一次增重会将原日期向前滚动到符合频率规则的下一个日期
print now+MonthEnd()
print now+MonthEnd(2)
结果为:
2011-11-30 00:00:00
2011-12-31 00:00:00
通过锚点偏移量的rollforward和rollback方法,可显式地将日期向前或向后“滚动”
offset=MonthEnd()
print offset.rollforward(now)
print offset.rollback(now)
结果为:
2011-11-30 00:00:00
2011-10-31 00:00:00
日期偏移量还有一个巧妙的用法,即结合groupby使用这两个滚动方法
ts=Series(np.random.randn(20),index=pd.date_range('1/15/2000',periods=20,freq='4d'))
print ts.groupby(offset.rollforward).mean()
结果为:
2000-01-31 -0.024235
2000-02-29 -0.182988
2000-03-31 -0.458176
dtype: float64
更简单、更快速地是实现该功能的办法是使用resample
print ts.resample('M',how='mean')
结果为:
2000-01-31 -0.076951
2000-02-29 -0.093232
2000-03-31 -0.390766
Freq: M, dtype: float64
8.时区处理
时区名可以在文档中找到,也可以通过交互的方式查看
import pytz
print pytz.common_timezones[-5:]
结果为:
['US/Eastern', 'US/Hawaii', 'US/Mountain', 'US/Pacific', 'UTC']
要从pytz中获取时区对象,使用pytz.timezone即可
tz=pytz.timezone('US/Eastern')
print tz
结果为:
US/Eastern
9.本地化和转换
默认情况下,pandas中的时间序列是单纯的时区。看看下面这个时间序列
rng=pd.date_range('3/9/2012 9:30',periods=6,freq='D')
ts=Series(np.random.rand(len(rng)),index=rng)
其索引的tz字段为None
print ts.index.tz
结果为:
None
在生成日期范围的时候还可以加上一个时区集
print pd.date_range('3/9/2012 9:30',periods=10,freq='D',tz='UTC')
结果为:
DatetimeIndex(['2012-03-09 09:30:00+00:00', '2012-03-10 09:30:00+00:00',
'2012-03-11 09:30:00+00:00', '2012-03-12 09:30:00+00:00',
'2012-03-13 09:30:00+00:00', '2012-03-14 09:30:00+00:00',
'2012-03-15 09:30:00+00:00', '2012-03-16 09:30:00+00:00',
'2012-03-17 09:30:00+00:00', '2012-03-18 09:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq='D')
从单纯到本地化的转换是通过tz_localize方法处理的
ts_utc=ts.tz_localize('UTC')
print ts_utc
结果为:
2012-03-09 09:30:00+00:00 0.641279
2012-03-10 09:30:00+00:00 0.275813
2012-03-11 09:30:00+00:00 0.113782
2012-03-12 09:30:00+00:00 0.073940
2012-03-13 09:30:00+00:00 0.087528
2012-03-14 09:30:00+00:00 0.458625
Freq: D, dtype: float64
print ts_utc.index
结果为:
DatetimeIndex(['2012-03-09 09:30:00+00:00', '2012-03-10 09:30:00+00:00',
'2012-03-11 09:30:00+00:00', '2012-03-12 09:30:00+00:00',
'2012-03-13 09:30:00+00:00', '2012-03-14 09:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq='D')
一旦时间序列被本地化到某个特定时区,就可以用tz_convert将其转换到别的时区了
print ts_utc.tz_convert('US/Eastern')
结果为:
2012-03-09 04:30:00-05:00 0.595619
2012-03-10 04:30:00-05:00 0.337900
2012-03-11 05:30:00-04:00 0.552080
2012-03-12 05:30:00-04:00 0.922716
2012-03-13 05:30:00-04:00 0.311070
2012-03-14 05:30:00-04:00 0.682581
Freq: D, dtype: float64
对于上面这种时间序列(它跨越了美国东部时区的夏令时转变期),我们可以将其本地化到EST,然后转换为UTC或柏林时间
ts_eastern=ts.tz_localize('US/Eastern')
print ts_eastern.tz_convert('UTC')
结果为:
2012-03-09 14:30:00+00:00 0.696696
2012-03-10 14:30:00+00:00 0.798250
2012-03-11 13:30:00+00:00 0.237720
2012-03-12 13:30:00+00:00 0.826396
2012-03-13 13:30:00+00:00 0.304436
2012-03-14 13:30:00+00:00 0.162294
Freq: D, dtype: float64
print ts_eastern.tz_convert('Europe/Berlin')
结果为:
2012-03-09 15:30:00+01:00 0.116943
2012-03-10 15:30:00+01:00 0.805555
2012-03-11 14:30:00+01:00 0.765655
2012-03-12 14:30:00+01:00 0.762651
2012-03-13 14:30:00+01:00 0.947182
2012-03-14 14:30:00+01:00 0.670358
Freq: D, dtype: float64
tz_localize和tz_convert也是DatatimeIndex的实例方法
结果为:
print 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')
10.操作时区意识型Timestamp对象
跟时间序列和日期范围差不多,Timestamp对象也能从单纯型本地化为时区意识型,并从一个时区转换到另一个时区
stamp=pd.Timestamp('2011-03-12 04:00')
stamp_utc=stamp.tz_localize('utc')
print stamp_utc.tz_convert('US/Eastern')
结果为:
2011-03-11 23:00:00-05:00
在创建Timestamp时,还可以传入一个时区信息
stamp_moscow=pd.Timestamp('2011-03-12 04:00',tz='Europe/Moscow')
print stamp_moscow
结果为:
2011-03-12 04:00:00+03:00
时区意识型Timestamp对象在内部保存了一个UTC时间戳值。这个UTC值在时区转换过程中是不会发生变化的
print stamp_utc.value
print stamp_utc.tz_convert('US/Eastern').value
结果为:
1299902400000000000
1299902400000000000
当使用pandas的DateOffset对象执行时间算术运算时,运算过程中会自动关注是否存在夏令时转变期
from pandas.tseries.offsets import Hour
#夏令时转变前30分钟
stamp=pd.Timestamp('2012-03-12 01:30',tz='US/Eastern')
print stamp
print stamp+Hour()
#夏令时转变前90分钟
stamp=pd.Timestamp('2012-11-04 00:30',tz='US/Eastern')
print stamp
print stamp+2*Hour()
结果为:
2012-03-12 01:30:00-04:00
2012-03-12 02:30:00-04:00
2012-11-04 00:30:00-04:00
2012-11-04 01:30:00-05:00
11.不同时区之间的运算
如果两个时间序列的时区不同,在将它们合并到一起时,最终结果就会是UTC。由于时间戳其实是你UTC存储的,所以这是一个很简单的运算,并不需要发生任何转换
rng=pd.date_range('3/7/2012 09:30',periods=10,freq='B')
ts=Series(np.random.randn(len(rng)),index=rng)
print ts
结果为:
2012-03-07 09:30:00 1.533603
2012-03-08 09:30:00 -0.224899
2012-03-09 09:30:00 0.542026
2012-03-12 09:30:00 -0.815753
2012-03-13 09:30:00 -1.421795
2012-03-14 09:30:00 0.399534
2012-03-15 09:30:00 0.293016
2012-03-16 09:30:00 -1.612594
2012-03-19 09:30:00 0.072332
2012-03-20 09:30:00 0.313340
Freq: B, dtype: float64
ts1=ts[:7].tz_localize('Europe/London')
ts2=ts1[2:].tz_convert('Europe/Moscow')
result=ts1+ts2
print result.index
结果为:
DatetimeIndex(['2012-03-07 09:30:00+00:00', '2012-03-08 09:30:00+00:00',
'2012-03-09 09:30:00+00:00', '2012-03-12 09:30:00+00:00',
'2012-03-13 09:30:00+00:00', '2012-03-14 09:30:00+00:00',
'2012-03-15 09:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq='B')
12.日期及其算术运算
时期表示的是时间区间,比如数日、数月、数季、数年等。Period类所表示的就是这种数据类型,其构造函数需要用到一个字符串或整数,以及表中的频率
p=pd.Period(2007,freq='A-DEC')
print p
结果为:
2007
这个Period对象表示的是从2007年1月1日到2007年12月31日之间的整段时间。只需对Period对象加上或减去一个整数即可达到根据其频率进行位移的效果
print p+5
print p-2
结果为:
2012
2005
如果两个Period对象拥有相同的频率,则它们的差就是它们之间的单位数量
print pd.Period('2014',freq='A-DEC')-p
结果为:
7
period_range函数可用于创建规则的时期范围
rng=pd.date_range('1/1/2000','6/30/2000',freq='M')
print rng
结果为:
DatetimeIndex(['2000-01-31', '2000-02-29', '2000-03-31', '2000-04-30',
'2000-05-31', '2000-06-30'],
dtype='datetime64[ns]', freq='M')
PeriodIndex类保存了一组Period,它可以在任何pandas数据结构中被用做轴索引
print Series(np.random.randn(6),index=rng)
结果为:
2000-01-31 -1.375039
2000-02-29 -0.143529
2000-03-31 2.162475
2000-04-30 2.109093
2000-05-31 0.759747
2000-06-30 -1.994800
Freq: M, dtype: float64
PeriodIndex类的构造函数还允许直接使用一组字符串
values=['2001Q3','2002Q2','2003Q1']
index=pd.PeriodIndex(values,freq='Q-DEC')
print index
结果为:
PeriodIndex(['2001Q3', '2002Q2', '2003Q1'], dtype='int64', freq='Q-DEC')
相关文章推荐
- Python动态类型的学习---引用的理解
- Python3写爬虫(四)多线程实现数据爬取
- 垃圾邮件过滤器 python简单实现
- 下载并遍历 names.txt 文件,输出长度最长的回文人名。
- install and upgrade scrapy
- Scrapy的架构介绍
- Centos6 编译安装Python
- 使用Python生成Excel格式的图片
- 让Python文件也可以当bat文件运行
- [Python]推算数独
- Python中zip()函数用法举例
- Python中map()函数浅析
- Python将excel导入到mysql中
- Python在CAM软件Genesis2000中的应用
- 使用Shiboken为C++和Qt库创建Python绑定
- FREEBASIC 编译可被python调用的dll函数示例
- Python 七步捉虫法